From ae6743c1a14e1ddbb3c2ca88170ea80d2b56812a Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Sun, 8 Aug 2021 15:02:10 +0200 Subject: [PATCH] Math.NET Numerics: 5.0.0-alpha02 docs update --- Build.html | 400 +++++++--------- CSV.html | 297 ++++++------ Compatibility.html | 281 ++++++------ Constants.html | 275 +++++------ Contributing.html | 281 ++++++------ Contributors.html | 275 +++++------ DescriptiveStatistics.html | 538 ++++++++-------------- Distance.html | 351 +++++++------- DistanceCanberra.png | Bin 0 -> 11444 bytes DistanceChebyshev.png | Bin 0 -> 9000 bytes DistanceCosine.png | Bin 0 -> 3591 bytes DistanceEuclidean.png | Bin 0 -> 11198 bytes DistanceMAE.png | Bin 0 -> 12631 bytes DistanceMSE.png | Bin 0 -> 13185 bytes DistanceManhattan.png | Bin 0 -> 11552 bytes DistanceMinkowski3.png | Bin 0 -> 9695 bytes DistancePearson.png | Bin 0 -> 3838 bytes DistanceSAD.png | Bin 0 -> 11552 bytes DistanceSSD.png | Bin 0 -> 13169 bytes Dockerfile | 85 ++++ Euclid.html | 307 ++++++------- Functions.html | 284 ++++++------ Generate.html | 418 ++++++++--------- IFsharpNotebook.html | 517 ++++++++++----------- IfSharp-GenerateIS.png | Bin 0 -> 31942 bytes IfSharp-MatrixVector.png | Bin 0 -> 47785 bytes IntegralTransforms.html | 291 ++++++------ Integration.html | 384 ++++++---------- Interpolation.html | 281 ++++++------ LinearEquations.html | 346 +++++++------- MKL.html | 400 +++++++--------- MatlabFiles.html | 329 ++++++-------- Matrix.html | 804 ++++++++++++--------------------- MatrixMarket.html | 291 ++++++------ NuGet.config | 14 + Packages.html | 281 ++++++------ Probability.html | 638 +++++++++++--------------- Random.html | 495 ++++++++------------ Regression.html | 373 +++++++-------- ReleaseNotes-MKL.html | 281 ++++++------ ReleaseNotes-OpenBLAS.html | 281 ++++++------ ReleaseNotes.html | 275 +++++------ Users.html | 275 +++++------ content/fsdocs-custom.css | 5 + content/fsdocs-default.css | 594 ++++++++++++++++++++++++ content/fsdocs-search.js | 84 ++++ content/fsdocs-tips.js | 54 +++ content/img/copy-md-hover.png | Bin 0 -> 2886 bytes content/img/copy-md.png | Bin 0 -> 3351 bytes content/img/copy-xml-hover.png | Bin 0 -> 3192 bytes content/img/copy-xml.png | Bin 0 -> 3486 bytes content/img/github-hover.png | Bin 0 -> 7695 bytes content/img/github.png | Bin 806 -> 7642 bytes content/navbar-fixed-left.css | 77 ++++ content/navbar-fixed-right.css | 78 ++++ index.html | 414 +++++++---------- index.json | 1 + logo.png | Bin 0 -> 16028 bytes 58 files changed, 5792 insertions(+), 5863 deletions(-) create mode 100644 DistanceCanberra.png create mode 100644 DistanceChebyshev.png create mode 100644 DistanceCosine.png create mode 100644 DistanceEuclidean.png create mode 100644 DistanceMAE.png create mode 100644 DistanceMSE.png create mode 100644 DistanceManhattan.png create mode 100644 DistanceMinkowski3.png create mode 100644 DistancePearson.png create mode 100644 DistanceSAD.png create mode 100644 DistanceSSD.png create mode 100644 Dockerfile create mode 100644 IfSharp-GenerateIS.png create mode 100644 IfSharp-MatrixVector.png create mode 100644 NuGet.config create mode 100644 content/fsdocs-custom.css create mode 100644 content/fsdocs-default.css create mode 100644 content/fsdocs-search.js create mode 100644 content/fsdocs-tips.js create mode 100644 content/img/copy-md-hover.png create mode 100644 content/img/copy-md.png create mode 100644 content/img/copy-xml-hover.png create mode 100644 content/img/copy-xml.png create mode 100644 content/img/github-hover.png create mode 100644 content/navbar-fixed-left.css create mode 100644 content/navbar-fixed-right.css create mode 100644 index.json create mode 100644 logo.png diff --git a/Build.html b/Build.html index 87f6e19d..5aef5c46 100644 --- a/Build.html +++ b/Build.html @@ -1,63 +1,138 @@ - - - Building Math.NET Numerics + +<head> + <meta charset="utf-8"> + <title>Building Math.NET Numerics - - - + + + + + + - - - - + - - - - - + + + + + + + + + + + + - - - -
-
- -

Math.NET Numerics

+ + +
+ +
+
+

Building Math.NET Numerics

If you do not want to use the official binaries, or if you like to modify, debug or contribute, you can compile locally either using Visual Studio or manually with the build scripts.

@@ -75,52 +150,30 @@ may fail to compile or provide correct IntelliSense.

Instead of a compatible IDE you can also build the solutions directly with the .NET Core SDK build tools. You may need to run restore.cmd or restore.sh before, once after every git checkout in order to restore the dependencies.

- - - -
1: 
-2: 
-
restore.cmd (or ./restore.sh)
-dotnet build MathNet.Numerics.sln
-
+
restore.cmd (or ./restore.sh)
+dotnet build MathNet.Numerics.sln
+

FAKE

The fully automated build including unit tests, documentation and api reference, NuGet and Zip packages is using FAKE.

FAKE itself is not included in the repository but it will download and bootstrap itself automatically when build.cmd is run the first time. Note that this step is not required when using Visual Studio or the .NET Core SDK directly.

- - - -
 1: 
- 2: 
- 3: 
- 4: 
- 5: 
- 6: 
- 7: 
- 8: 
- 9: 
-10: 
-11: 
-12: 
-13: 
-14: 
-
./build.sh   # normal build and unit tests, when using bash shell on Windows or Linux.
-build.cmd    # normal build and unit tests, when using Windows CMD shell.
+
./build.sh   # normal build and unit tests, when using bash shell on Windows or Linux.
+build.cmd    # normal build and unit tests, when using Windows CMD shell.
 
-./build.sh build              # normal build
-./build.sh build strongname   # normal build and also build strong-named variant
+./build.sh build              # normal build
+./build.sh build strongname   # normal build and also build strong-named variant
 
-./build.sh test          # normal build, run unit tests
-./build.sh test quick    # normal build, run unit tests except long running ones
+./build.sh test          # normal build, run unit tests
+./build.sh test quick    # normal build, run unit tests except long running ones
 
-./build.sh clean         # cleanup build artifacts
-./build.sh docs          # generate documentation
-./build.sh api           # generate api reference
+./build.sh clean         # cleanup build artifacts
+./build.sh docs          # generate documentation
+./build.sh api           # generate api reference
 
-./build.sh all           # build, test, docs, api reference
-
+./build.sh all # build, test, docs, api reference +

If the build or tests fail claiming that FSharp.Core was not be found, see fsharp.org or install the Visual F# 3.0 Tools directly.

@@ -156,30 +209,12 @@ first add a new release header and change notes on top of the RELEASENOTES document in the root directory. The fake builds pick this up and propagate it to the assembly info files automatically.

The build can then be launched by calling:

- - - -
1: 
-
./build.sh all
-
+
./build.sh all
+

The build script will print the current version as part of the the header banner, which is also included in the release notes document in the build artifacts. Example:

- - - -
 1: 
- 2: 
- 3: 
- 4: 
- 5: 
- 6: 
- 7: 
- 8: 
- 9: 
-10: 
-11: 
-12: 
-13: 
-
//  __  __       _   _       _   _ ______ _______
+
//  __  __       _   _       _   _ ______ _______
 // |  \/  |     | | | |     | \ | |  ____|__   __|
 // | \  / | __ _| |_| |__   |  \| | |__     | |
 // | |\/| |/ _` | __| '_ \  | . ` |  __|    | |
@@ -192,9 +227,7 @@ Example:

// Math.NET Numerics v3.5.0 // Math.NET Numerics MKL Provider v1.7.0 // Math.NET Numerics Data Extensions v3.1.0 -
+

The artifacts are then ready in the out/packages directory.

Extra Packages

In addition to the core package this repository also include extra packages @@ -218,16 +251,10 @@ Visual Studio 2019, with the following options

The build can then be triggered by calling:

- - - -
1: 
-2: 
-3: 
-
./build.sh MklWinBuild  // build both 32 and 64 bit variants
-./build.sh MklTest      // run all tests with the MKL provider enforced
-./build.sh MklWinAll    // build and run tests
-
+
./build.sh MklWinBuild  // build both 32 and 64 bit variants
+./build.sh MklTest      // run all tests with the MKL provider enforced
+./build.sh MklWinAll    // build and run tests
+

If you run into an error with mkl_link_tool.exe you may need to patch a targets file, see MKL 2020.1, VS2019 linking bug .

The build puts the binaries to out/MKL/Windows/x64 (and x86), the NuGet package @@ -240,30 +267,18 @@ this is also what the unit tests do when you run the MklTest build

  • Update CONTRIBUTORS.md file (via git shortlog -sn)

  • Build Release:

    - - - -
    1: 
    -
    build.sh all strongname
    -
    +
    build.sh all strongname
    +
  • Commit and push release notes and (auto-updated) assembly info files with new "Release: v1.2.3" commit
  • Publish Release:

    - - - -
    1: 
    -2: 
    -3: 
    -4: 
    -5: 
    -
    build.sh PublishDocs
    -build.sh PublishApi
    -build.sh PublishTag
    -build.sh PublishArchive
    -build.sh PublishNuGet
    -
    +
    build.sh PublishDocs
    +build.sh PublishApi
    +build.sh PublishTag
    +build.sh PublishArchive
    +build.sh PublishNuGet
    +
  • Consider a tweet via @MathDotNet

  • @@ -273,90 +288,21 @@ this is also what the unit tests do when you run the MklTest build
  • -
    type unit = Unit

    Full name: Microsoft.FSharp.Core.unit
    -
    val using : resource:'T -> action:('T -> 'U) -> 'U (requires 'T :> System.IDisposable)

    Full name: Microsoft.FSharp.Core.Operators.using
    +
    type unit = Unit
    <summary>The type 'unit', which has only one value "()". This value is special and + always uses the representation 'null'.</summary>
    <category index="1">Basic Types</category>
    +
    val using : resource:'T -> action:('T -> 'U) -> 'U (requires 'T :> System.IDisposable)
    <summary>Clean up resources associated with the input object after the completion of the given function. + Cleanup occurs even when an exception is raised by the protected + code. </summary>
    <param name="resource">The resource to be disposed after action is called.</param>
    <param name="action">The action that accepts the resource.</param>
    <returns>The resulting value.</returns>
    -
    -
    - -
    -
    - + + + + + + + +
    + + diff --git a/CSV.html b/CSV.html index a4d848f1..be9e919e 100644 --- a/CSV.html +++ b/CSV.html @@ -1,72 +1,143 @@ - - - Delimited Text Files (CSV & TSV) + +<head> + <meta charset="utf-8"> + <title>Delimited Text Files (CSV & TSV) - - - - - - - - - - - - - - - - - - -
    -
    - -

    Math.NET Numerics

    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    +

    Delimited Text Files (CSV & TSV)

    Likely the most common file format for tabular data, delimited files like CSV store data as text with one line per row and values within rows separated by a comma. Such text files are supported by virtually all software that deals with tabular data.

    Example:

    - -
    1: 
    -2: 
    -3: 
    -
    A,B,C
    +
    A,B,C
     0.5,0.6,98.0
     2.0,3.4,5.3
     
    @@ -91,11 +162,7 @@ you can use this method using a StringReader.

    All these functions expect the data type of the matrix to be generated as generic type argument. Only Double, Single, Complex and Complex32 are supported.

    Example:

    - -
    1: 
    -2: 
    -3: 
    -
    using MathNet.Numerics.Data.Text;
    +
    using MathNet.Numerics.Data.Text;
     
     Matrix<double> matrix = DelimitedReader.Read<double>("data.csv", false, ",", true);
     
    @@ -145,9 +212,7 @@ Default: null.

    Example:

    - -
    1: 
    -
    DelimitedWriter.Write("data.csv", matrix, ",");
    +
    DelimitedWriter.Write("data.csv", matrix, ",");
     

    Alternatives

    The data extension packages also offer other ways to serialize a matrix to a binary stream or file. @@ -157,88 +222,16 @@ Among others:

  • MATLAB Level-5 Mat files
  • - - -
    - -
    - + - + + + + + + + + + + diff --git a/Compatibility.html b/Compatibility.html index b05e7c82..7dd33a1a 100644 --- a/Compatibility.html +++ b/Compatibility.html @@ -1,63 +1,138 @@ - - - Platform Support + +<head> + <meta charset="utf-8"> + <title>Platform Support - - - - - - - - - - - - - - - - - - -
    -
    - -

    Math.NET Numerics

    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    +

    Platform Support

    Supported Platforms:

    • .NET 5.0 or higher, with builds for 5.0.
    • @@ -76,88 +151,16 @@
    • F#: additionally FSharp.Core
    - -
    -
    - -
    -
    +
    - + + + + + + + +
    + + diff --git a/Constants.html b/Constants.html index e10a01b7..7fe79f3f 100644 --- a/Constants.html +++ b/Constants.html @@ -1,63 +1,138 @@ - - - Constants + +<head> + <meta charset="utf-8"> + <title>Constants - - - + + + + + + - - - - + - - - - - + + + + + + + + + + + + - - - -
    -
    - -

    Math.NET Numerics

    + + +
    + +
    +
    +

    Constants

    Math.NET Numerics contains a set of often used mathematical and scientific constants. Mathematical and defined scientific constants are as accurate as double precision allows, while measured constants are implemented according @@ -820,88 +895,16 @@ to 2007 CODATA.

    - - -
    - -
    - + - + + + + + + + + + + diff --git a/Contributing.html b/Contributing.html index cf2f7867..bbbbc47c 100644 --- a/Contributing.html +++ b/Contributing.html @@ -1,63 +1,138 @@ - - - Contribute to Math.NET Numerics + +<head> + <meta charset="utf-8"> + <title>Contribute to Math.NET Numerics - - - - - - - - - - - - - - - - - - -
    -
    - -

    Math.NET Numerics

    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    +

    Contribute to Math.NET Numerics

    Math.NET Numerics is driven by the community and contributors like you. I'm excited that you're interested to help us move forward and improve Numerics. We usually accept contributions and try to attribute them properly, provided they keep the library consistent, focused and mathematically accurate. Have a look at the following tips to get started quickly. I'm looking forward to your pull requests! Thanks!

    — Christoph Rüegg (@cdrnet)

    Getting Started

    @@ -94,88 +169,16 @@ We try to follow semantic versioning, meaning

    Merges:
    Please avoid merging mainline back into your pull request branch. If you need to leverage some changes recently added to mainline, consider to rebase instead. In other words, please make sure your commits sit directly on top of a recent mainline master.

    - -
    -
    - -
    -
    +
    - + + + + + + + +
    + + diff --git a/Contributors.html b/Contributors.html index 3e109f8e..0e36402a 100644 --- a/Contributors.html +++ b/Contributors.html @@ -1,63 +1,138 @@ - - - Math.NET Numerics Contributors + +<head> + <meta charset="utf-8"> + <title>Math.NET Numerics Contributors - - - + + + + + + - - - - + - - - - - + + + + + + + + + + + + - - - -
    -
    - -

    Math.NET Numerics

    + + +
    + +
    +
    +

    Math.NET Numerics Contributors

    The Math.NET project is a community effort. We accept contributions and pull requests, but other support like submitting issues or helping the community are just as valuable. Why don't you join us as well?

    Thanks for all the contributions!

    Maintainers

    @@ -227,88 +302,16 @@ This section is incomplete - let us know if we forgot something.

  • Xamarin (license)
  • - -
    -
    - -
    -
    +
    - + + + + + + + +
    + + diff --git a/DescriptiveStatistics.html b/DescriptiveStatistics.html index f3990a94..6381b422 100644 --- a/DescriptiveStatistics.html +++ b/DescriptiveStatistics.html @@ -1,68 +1,141 @@ - - - Descriptive Statistics + +<head> + <meta charset="utf-8"> + <title>Descriptive Statistics - - - + + + + + + - - - - + - - - - - + + + + + + + + + + + + - - - -
    -
    - -

    Math.NET Numerics

    + + +
    + +
    +
    +

    Descriptive Statistics

    Initialization

    We need to reference Math.NET Numerics and open the statistics namespace:

    - -
    1: 
    -
    using MathNet.Numerics.Statistics;
    +
    using MathNet.Numerics.Statistics;
     

    Univariate Statistical Analysis

    The primary class for statistical analysis is Statistics which provides common @@ -88,21 +161,7 @@ Useful if data larger than local memory is streamed directly from a disk or netw

    Another alternative, in case you need to gather a whole set of statistical characteristics in one pass, is provided by the DescriptiveStatistics class:

    - -
     1: 
    - 2: 
    - 3: 
    - 4: 
    - 5: 
    - 6: 
    - 7: 
    - 8: 
    - 9: 
    -10: 
    -11: 
    -12: 
    -13: 
    -
    var samples = new ChiSquare(5).Samples().Take(1000);
    +
    var samples = new ChiSquare(5).Samples().Take(1000);
     var statistics = new DescriptiveStatistics(samples);
     
     var largestElement = statistics.Maximum;
    @@ -123,11 +182,7 @@ and StreamingStatistics. The one in SortedArrayStatistics
     

    Both min and max are directly affected by outliers and are therefore no robust statistics at all. For a more robust alternative, consider using Quantiles instead.

    - -
    1: 
    -2: 
    -3: 
    -
    var samples = new ChiSquare(5).Samples().Take(1000).ToArray();
    +
    var samples = new ChiSquare(5).Samples().Take(1000).ToArray();
     var largestElement = samples.Maximum();
     var smallestElement = samples.Minimum();
     
    @@ -139,26 +194,15 @@ The mean is affected by outliers, so if you need a more robust estimate consider StreamingStatistics.Mean(stream) ArrayStatistics.Mean(data)

    \[\overline{x} = \frac{1}{N}\sum_{i=1}^N x_i\]

    - - - -
    1: 
    -2: 
    -3: 
    -4: 
    -5: 
    -6: 
    -7: 
    -8: 
    -
    let whiteNoise = Generate.Normal(1000, mean=10.0, standardDeviation=2.0)
    +
    let whiteNoise = Generate.Normal(1000, mean=10.0, standardDeviation=2.0)
     val samples : float [] = [|12.90021939; 9.631515037; 7.810008046; 14.13301053; ...|] 
    -Statistics.Mean whiteNoise
    +Statistics.Mean whiteNoise
     val it : float = 10.02162347
     
    -let wave = Generate.Sinusoidal(1000, samplingRate=100., frequency=5., amplitude=0.5)
    -Statistics.Mean wave
    +let wave = Generate.Sinusoidal(1000, samplingRate=100., frequency=5., amplitude=0.5)
    +Statistics.Mean wave
     val it : float = -4.133520783e-17
    -
    +

    Variance and Standard Deviation

    Variance \(\sigma^2\) and the Standard Deviation \(\sigma\) are measures of how far the samples are spread out.

    If the whole population is available, the functions with the Population-prefix @@ -172,38 +216,23 @@ Bessel's correction with an \(N-1\) normalizer to a sa

    Statistics.Variance(samples) Statistics.StandardDeviation(samples)

    \[s^2 = \frac{1}{N-1}\sum_{i=1}^N (x_i - \overline{x})^2\]

    - - - -
    1: 
    -2: 
    -3: 
    -4: 
    -5: 
    -6: 
    -7: 
    -
    Statistics.Variance whiteNoise
    +
    Statistics.Variance whiteNoise
     val it : float = 3.819436094
    -Statistics.StandardDeviation whiteNoise
    +Statistics.StandardDeviation whiteNoise
     val it : float = 1.954337764
     
    -Statistics.Variance wave
    +Statistics.Variance wave
     val it : float = 0.1251251251
    -
    +

    Combined Routines

    Since mean and variance are often needed together, there are routines that evaluate both in a single pass:

    Statistics.MeanVariance(samples) ArrayStatistics.MeanVariance(samples) StreamingStatistics.MeanVariance(samples)

    - - - -
    1: 
    -2: 
    -
    Statistics.MeanVariance whiteNoise
    +
    Statistics.MeanVariance whiteNoise
     val it : float * float = (10.02162347, 3.819436094)
    -
    +

    Covariance

    The sample covariance is an estimation of the Covariance, a measure of how much two random variables change together. Similarly to the variance above, there are two versions in order to @@ -212,18 +241,11 @@ apply Bessel's correction to bias in case of sample data.

    \[q = \frac{1}{N-1}\sum_{i=1}^N (x_i - \overline{x})(y_i - \overline{y})\]

    Statistics.PopulationCovariance(population1, population2)

    \[q = \frac{1}{N}\sum_{i=1}^N (x_i - \mu_x)(y_i - \mu_y)\]

    - - - -
    1: 
    -2: 
    -3: 
    -4: 
    -
    Statistics.Covariance(whiteNoise, whiteNoise)
    +
    Statistics.Covariance(whiteNoise, whiteNoise)
     val it : float = 3.819436094
    -Statistics.Covariance(whiteNoise, wave)
    +Statistics.Covariance(whiteNoise, wave)
     val it : float = 0.04397985084
    -
    +

    Order Statistics

    Order Statistic

    The k-th order statistic of a sample set is the k-th smallest value. Note that, @@ -244,34 +266,19 @@ provided data and then on each invocation uses efficient sorted algorithms:

    Statistics.OrderStatisticFunc(data)

    Such Inplace and Func variants are a common pattern throughout the Statistics class and also the rest of the library.

    - - - -
     1: 
    - 2: 
    - 3: 
    - 4: 
    - 5: 
    - 6: 
    - 7: 
    - 8: 
    - 9: 
    -10: 
    -11: 
    -12: 
    -
    Statistics.OrderStatistic(whiteNoise, 1)
    +
    Statistics.OrderStatistic(whiteNoise, 1)
     val it : float = 3.633070184
    -Statistics.OrderStatistic(whiteNoise, 1000)
    +Statistics.OrderStatistic(whiteNoise, 1000)
     val it : float = 16.65183566
     
    -let os = Statistics.orderStatisticFunc whiteNoise
    -os 250
    +let os = Statistics.orderStatisticFunc whiteNoise
    +os 250
     val it : float = 8.645491746
    -os 500
    +os 500
     val it : float = 10.11872428
    -os 750
    +os 750
     val it : float = 11.33170746
    -
    +

    Median

    Median is a robust indicator of central tendency and much less affected by outliers than the sample mean. The median is estimated by the value exactly in the middle of @@ -283,18 +290,11 @@ the sorted set of samples and thus separating the higher half of the data from t uses the default quantile definition, which is equivalent to mode 8 in R and is approximately median-unbiased regardless of the sample distribution. If you need another convention, use QuantileCustom instead, see below for details.

    - - - -
    1: 
    -2: 
    -3: 
    -4: 
    -
    Statistics.Median whiteNoise
    +
    Statistics.Median whiteNoise
     val it : float = 10.11872428
    -Statistics.Median wave
    +Statistics.Median wave
     val it : float = -2.452600839e-16
    -
    +

    Quartiles and the 5-number summary

    Quartiles group the ascendingly sorted data into four equal groups, where each group represents a quarter of the data. The lower quartile is estimated by @@ -307,50 +307,31 @@ estimates the median as discussed above.

    SortedArrayStatistics.UpperQuartile(data) ArrayStatistics.LowerQuartileInplace(data) ArrayStatistics.UpperQuartileInplace(data)

    - - - -
    1: 
    -2: 
    -3: 
    -4: 
    -
    Statistics.LowerQuartile whiteNoise
    +
    Statistics.LowerQuartile whiteNoise
     val it : float = 8.645491746
    -Statistics.UpperQuartile whiteNoise
    +Statistics.UpperQuartile whiteNoise
     val it : float = 11.33213732
    -
    +

    Using that data we can provide a useful set of indicators usually named 5-number summary, which consists of the minimum value, the lower quartile, the median, the upper quartile and the maximum value. All these values can be visualized in the popular box plot diagrams.

    Statistics.FiveNumberSummary(data) SortedArrayStatistics.FiveNumberSummary(data) ArrayStatistics.FiveNumberSummaryInplace(data)

    - - - -
    1: 
    -2: 
    -3: 
    -4: 
    -
    Statistics.FiveNumberSummary whiteNoise
    +
    Statistics.FiveNumberSummary whiteNoise
     val it : float [] = [|3.633070184; 8.645937823; 10.12165054; 11.33213732; 16.65183566|] 
    -Statistics.FiveNumberSummary wave
    +Statistics.FiveNumberSummary wave
     val it : float [] = [|-0.5; -0.3584185509; -2.452600839e-16; 0.3584185509; 0.5|] 
    -
    +

    The difference between the upper and the lower quartile is called inter-quartile range (IQR) and is a robust indicator of spread. In box plots the IQR is the total height of the box.

    Statistics.InterquartileRange(data) SortedArrayStatistics.InterquartileRange(data) ArrayStatistics.InterquartileRangeInplace(data)

    Just like median, quartiles use the default R8 quantile definition internally.

    - - - -
    1: 
    -2: 
    -
    Statistics.InterquartileRange whiteNoise
    +
    Statistics.InterquartileRange whiteNoise
     val it : float = 2.686199498
    -
    +

    Percentiles

    Percentiles extend the concept further by grouping the sorted values into 100 equal groups and looking at the 101 places (0,1,..,100) between and around them. @@ -361,18 +342,11 @@ The 0-percentile represents the minimum value, 25 the first quartile, 50 the med SortedArrayStatistics.Percentile(data, p) ArrayStatistics.PercentileInplace(data, p)

    Just like median, percentiles use the default R8 quantile definition internally.

    - - - -
    1: 
    -2: 
    -3: 
    -4: 
    -
    Statistics.Percentile(whiteNoise, 5)
    +
    Statistics.Percentile(whiteNoise, 5)
     val it : float = 6.693373507
    -Statistics.Percentile(whiteNoise, 98)
    +Statistics.Percentile(whiteNoise, 98)
     val it : float = 13.97580653
    -
    +

    Quantiles

    Instead of grouping into 4 or 100 boxes, quantiles generalize the concept to an infinite number of boxes and thus to arbitrary real numbers \(\tau\) between 0.0 and 1.0, where 0.0 represents the @@ -382,14 +356,9 @@ the inverse cumulative distribution function of the sample distribution.

    Statistics.QuantileFunc(data) SortedArrayStatistics.Quantile(data, tau) ArrayStatistics.QuantileInplace(data, tau)

    - - - -
    1: 
    -2: 
    -
    Statistics.Quantile(whiteNoise, 0.98)
    +
    Statistics.Quantile(whiteNoise, 0.98)
     val it : float = 13.97580653
    -
    +

    Quantile Conventions and Compatibility

    Remember that all these descriptive statistics do not compute but merely estimate statistical indicators of the value distribution. In the case of quantiles, @@ -440,22 +409,13 @@ Similar to QuantileDefinition, the RankDefinition enum

    Statistics.Ranks(data, definition) SortedArrayStatistics.Ranks(data, definition) ArrayStatistics.RanksInplace(data, definition)

    - - - -
    1: 
    -2: 
    -3: 
    -4: 
    -5: 
    -6: 
    -
    Statistics.Ranks(whiteNoise)
    +
    Statistics.Ranks(whiteNoise)
     val it : float [] = [|634.0; 736.0; 405.0; 395.0; 197.0; 167.0; 722.0; 44.0; ...|] 
    -Statistics.Ranks([| 13.0; 14.0; 11.0; 12.0; 13.0 |], RankDefinition.Average)
    +Statistics.Ranks([| 13.0; 14.0; 11.0; 12.0; 13.0 |], RankDefinition.Average)
     val it : float [] = [|3.5; 5.0; 1.0; 2.0; 3.5|] 
    -Statistics.Ranks([| 13.0; 14.0; 11.0; 12.0; 13.0 |], RankDefinition.Sports)
    +Statistics.Ranks([| 13.0; 14.0; 11.0; 12.0; 13.0 |], RankDefinition.Sports)
     val it : float [] = [|3.0; 5.0; 1.0; 2.0; 3.0|] 
    -
    +

    Quantile Rank

    Counterpart of the Quantile function, estimates \(\tau\) of the provided \(\tau\)-quantile value \(x\) from the provided samples. The \(\tau\)-quantile is the data value where the cumulative distribution @@ -463,165 +423,63 @@ function crosses \(\tau\).

    Statistics.QuantileRank(data, x, definition) Statistics.QuantileRankFunc(data, definition) SortedArrayStatistics.QuantileRank(data, x, definition)

    - - - -
    1: 
    -2: 
    -3: 
    -4: 
    -
    Statistics.QuantileRank(whiteNoise, 13.0)
    +
    Statistics.QuantileRank(whiteNoise, 13.0)
     val it : float = 0.9370045563
    -Statistics.QuantileRank(whiteNoise, 6.7, RankDefinition.Average)
    +Statistics.QuantileRank(whiteNoise, 6.7, RankDefinition.Average)
     val it : float = 0.04960610389
    -
    +

    Empirical Distribution Functions

    Statistics.EmpiricalCDF(data, x) Statistics.EmpiricalCDFFunc(data) Statistics.EmpiricalInvCDF(data, tau) Statistics.EmpiricalInvCDFFunc(data) SortedArrayStatistics.EmpiricalCDF(data, x)

    - - - -
     1: 
    - 2: 
    - 3: 
    - 4: 
    - 5: 
    - 6: 
    - 7: 
    - 8: 
    - 9: 
    -10: 
    -11: 
    -12: 
    -13: 
    -
    let ecdf = Statistics.EmpiricalCDFFunc whiteNoise
    -Generate.LinearSpacedMap(20, start=3.0, stop=17.0, map=ecdf)
    +
    let ecdf = Statistics.EmpiricalCDFFunc whiteNoise
    +Generate.LinearSpacedMap(20, start=3.0, stop=17.0, map=ecdf)
     val it : float [] =
         [|0.0; 0.001; 0.002; 0.005; 0.022; 0.05; 0.094; 0.172; 0.278; 0.423; 0.555; 
           0.705; 0.843; 0.921; 0.944; 0.983; 0.992; 0.997; 0.999; 1.0|] 
     
    -let eicdf = Statistics.empiricalInvCDFFunc whiteNoise
    -[ for tau in 0.0..0.05..1.0 -> eicdf tau ]
    +let eicdf = Statistics.empiricalInvCDFFunc whiteNoise
    +[ for tau in 0.0..0.05..1.0 -> eicdf tau ]
     val it : float [] =
         [3.633070184; 6.682142043; 7.520000817; 8.040513497; 8.347587493; 
          8.645491746; 9.02681611; 9.298987151; 9.522627142; 9.819352699; 10.11872428; 
          10.35991046; 10.57530906; 10.8259542; 11.08605473; 11.33170746; 11.54356436; 
          11.90973541; 12.4294346; 13.36889423; 16.65183566] 
    -
    +

    Histograms

    A histogram can be computed using the Histogram class. Its constructor takes the samples enumerable, the number of buckets to create, plus optionally the range (minimum, maximum) of the sample data if available.

    - -
    1: 
    -2: 
    -
    var histogram = new Histogram(samples, 10);
    +
    var histogram = new Histogram(samples, 10);
     var bucket3count = histogram[2].Count;
     

    Correlation

    The Correlation class supports computing Pearson's product-momentum and Spearman's ranked correlation coefficient, as well as their correlation matrix for a set of vectors.

    Code Sample: Computing the correlation coefficient of 1000 samples of f(x) = 2x and g(x) = x^2:

    - -
    1: 
    -2: 
    -3: 
    -
    double[] dataF = Generate.LinearSpacedMap(1000, 0, 100, x => 2*x);
    +
    double[] dataF = Generate.LinearSpacedMap(1000, 0, 100, x => 2*x);
     double[] dataG = Generate.LinearSpacedMap(1000, 0, 100, x => x*x);
     double correlation = Correlation.Pearson(dataF, dataG);
     
    -
    val whiteNoise : obj

    Full name: DescriptiveStatistics.whiteNoise
    -
    val wave : obj

    Full name: DescriptiveStatistics.wave
    -
    val os : (int -> obj)

    Full name: DescriptiveStatistics.os
    -
    val ecdf : obj

    Full name: DescriptiveStatistics.ecdf
    -
    val eicdf : (float -> obj)

    Full name: DescriptiveStatistics.eicdf
    -
    val tau : float
    +
    val whiteNoise : obj
    +
    val wave : obj
    +
    val os : (int -> obj)
    +
    val ecdf : obj
    +
    val eicdf : (float -> obj)
    +
    val tau : float
    - -
    - -
    - - + + + + + + + + + + diff --git a/Distance.html b/Distance.html index 77a1e164..7f3c41ad 100644 --- a/Distance.html +++ b/Distance.html @@ -1,63 +1,138 @@ - - - Distance Metrics - - - - - - - - - - - - - - - - - - -
    -
    - -

    Math.NET Numerics

    + + + Distance Metrics + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    +

    Distance Metrics

    A metric or distance function is a function \(d(x,y)\) that defines the distance between elements of a set as a non-negative real number. If the distance is zero, both elements are equivalent under that specific metric. Distance functions thus provide a way to measure how close two elements are, where elements @@ -68,196 +143,100 @@ as error or cost functions to be minimized in an optimization problem.

    are valid metrics as well. Every normed vector space induces a distance given by \(d(\vec x, \vec y) = \|\vec x - \vec y\|\).

    Math.NET Numerics provides the following distance functions on vectors and arrays:

    Sum of Absolute Difference (SAD)

    - +

    The sum of absolute difference is equivalent to the \(L_1\)-norm of the difference, also known as Manhattan- or Taxicab-norm. The abs function makes this metric a bit complicated to deal with analytically, but it is more robust than SSD.

    \[d_{\mathbf{SAD}} : (x, y) \mapsto \|x-y\|_1 = \sum_{i=1}^{n} |x_i-y_i|\]

    - -
    1: 
    -
    double d = Distance.SAD(x, y);
    +
    double d = Distance.SAD(x, y);
     

    Sum of Squared Difference (SSD)

    - +

    The sum of squared difference is equivalent to the squared \(L_2\)-norm, also known as Euclidean norm. It is therefore also known as Squared Euclidean distance. This is the fundamental metric in least squares problems and linear algebra. The absence of the abs function makes this metric convenient to deal with analytically, but the squares cause it to be very sensitive to large outliers.

    \[d_{\mathbf{SSD}} : (x, y) \mapsto \|x-y\|_2^2 = \langle x-y, x-y\rangle = \sum_{i=1}^{n} (x_i-y_i)^2\]

    - -
    1: 
    -
    double d = Distance.SSD(x, y);
    +
    double d = Distance.SSD(x, y);
     

    Mean-Absolute Error (MAE)

    - +

    The mean absolute error is a normalized version of the sum of absolute difference.

    \[d_{\mathbf{MAE}} : (x, y) \mapsto \frac{d_{\mathbf{SAD}}}{n} = \frac{\|x-y\|_1}{n} = \frac{1}{n}\sum_{i=1}^{n} |x_i-y_i|\]

    - -
    1: 
    -
    double d = Distance.MAE(x, y);
    +
    double d = Distance.MAE(x, y);
     

    Mean-Squared Error (MSE)

    - +

    The mean squared error is a normalized version of the sum of squared difference.

    \[d_{\mathbf{MSE}} : (x, y) \mapsto \frac{d_{\mathbf{SSD}}}{n} = \frac{\|x-y\|_2^2}{n} = \frac{1}{n}\sum_{i=1}^{n} (x_i-y_i)^2\]

    - -
    1: 
    -
    double d = Distance.MSE(x, y);
    +
    double d = Distance.MSE(x, y);
     

    Euclidean Distance

    - +

    The euclidean distance is the \(L_2\)-norm of the difference, a special case of the Minkowski distance with p=2. It is the natural distance in a geometric interpretation.

    \[d_{\mathbf{2}} : (x, y) \mapsto \|x-y\|_2 = \sqrt{d_{\mathbf{SSD}}} = \sqrt{\sum_{i=1}^{n} (x_i-y_i)^2}\]

    - -
    1: 
    -
    double d = Distance.Euclidean(x, y);
    +
    double d = Distance.Euclidean(x, y);
     

    Manhattan Distance

    - +

    The Manhattan distance is the \(L_1\)-norm of the difference, a special case of the Minkowski distance with p=1 and equivalent to the sum of absolute difference.

    \[d_{\mathbf{1}} \equiv d_{\mathbf{SAD}} : (x, y) \mapsto \|x-y\|_1 = \sum_{i=1}^{n} |x_i-y_i|\]

    - -
    1: 
    -
    double d = Distance.Manhattan(x, y);
    +
    double d = Distance.Manhattan(x, y);
     

    Chebyshev Distance

    - +

    The Chebyshev distance is the \(L_\infty\)-norm of the difference, a special case of the Minkowski distance where p goes to infinity. It is also known as Chessboard distance.

    \[d_{\mathbf{\infty}} : (x, y) \mapsto \|x-y\|_\infty = \lim_{p \rightarrow \infty}\bigg(\sum_{i=1}^{n} |x_i-y_i|^p\bigg)^\frac{1}{p} = \max_{i} |x_i-y_i|\]

    - -
    1: 
    -
    double d = Distance.Chebyshev(x, y);
    +
    double d = Distance.Chebyshev(x, y);
     

    Minkowski Distance

    - +

    The Minkowski distance is the generalized \(L_p\)-norm of the difference. The contour plot on the left demonstrates the case of p=3.

    \[d_{\mathbf{p}} : (x, y) \mapsto \|x-y\|_p = \bigg(\sum_{i=1}^{n} |x_i-y_i|^p\bigg)^\frac{1}{p}\]

    - -
    1: 
    -
    double d = Distance.Minkowski(p, x, y);
    +
    double d = Distance.Minkowski(p, x, y);
     

    Canberra Distance

    - +

    The Canberra distance is a weighted version of the Manhattan distance, introduced and refined 1967 by Lance, Williams and Adkins. It is often used for data scattered around an origin, as it is biased for measures around the origin and very sensitive for values close to zero.

    \[d_{\mathbf{CAD}} : (x, y) \mapsto \sum_{i=1}^{n} \frac{|x_i-y_i|}{|x_i|+|y_i|}\]

    - -
    1: 
    -
    double d = Distance.Canberra(x, y);
    +
    double d = Distance.Canberra(x, y);
     

    Cosine Distance

    - +

    The cosine distance contains the dot product scaled by the product of the Euclidean distances from the origin. It represents the angular distance of two vectors while ignoring their scale.

    \[d_{\mathbf{cos}} : (x, y) \mapsto 1-\frac{\langle x, y\rangle}{\|x\|_2\|y\|_2} = 1-\frac{\sum_{i=1}^{n} x_i y_i}{\sqrt{\sum_{i=1}^{n} x_i^2}\sqrt{\sum_{i=1}^{n} y_i^2}}\]

    - -
    1: 
    -
    double d = Distance.Cosine(x, y);
    +
    double d = Distance.Cosine(x, y);
     

    Pearson's Distance

    - +

    The Pearson distance is a correlation distance based on Pearson's product-momentum correlation coefficient of the two sample vectors. Since the correlation coefficient falls between [-1, 1], the Pearson distance lies in [0, 2] and measures the linear relationship between the two vectors.

    \[d_{\mathbf{Pearson}} : (x, y) \mapsto 1 - \mathbf{Corr}(x, y)\]

    - -
    1: 
    -
    double d = Distance.Pearson(x, y);
    +
    double d = Distance.Pearson(x, y);
     

    Hamming Distance

    The hamming distance represents the number of entries in the two sample vectors which are different. It is a fundamental distance measure in information theory but less relevant in non-integer numerical problems.

    - -
    1: 
    -
    double d = Distance.Hamming(x, y);
    +
    double d = Distance.Hamming(x, y);
     
    - - -
    - -
    - + - + + + + + + + + + + diff --git a/DistanceCanberra.png b/DistanceCanberra.png new file mode 100644 index 0000000000000000000000000000000000000000..a1e3092034bdb77bf78c9931ec612d9a54b5e691 GIT binary patch literal 11444 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 N002ovPDHLkV1l%zr1Jm( literal 0 HcmV?d00001 diff --git a/DistanceEuclidean.png b/DistanceEuclidean.png new file mode 100644 index 0000000000000000000000000000000000000000..7aa858a5bbe8629cbb9f3e3cc560472c7a0389cd GIT binary patch literal 11198 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 literal 0 HcmV?d00001 diff --git a/DistanceMAE.png b/DistanceMAE.png new file mode 100644 index 0000000000000000000000000000000000000000..4423c49f052a63644681ed0cbf37c99055d7f093 GIT binary patch literal 12631 zcmV-dF{sXoP)G+<* zvZvWg7)5a`$}_9#?gs_F!@OGg?6m8u4N4y|%pg7>09A+FhAqGuQ_^vjP3Z{32ZVi0 z`XItm(j2h^&-stvdvU2?aST8!6JzN!hUpsjd&qv~T_ju&mPITJ#}LsP-`{+{#;HYH zCzO;-lZN#c#S1I(qBYNG93|%$)rz0ohM%L!R8z)cu?giEi%E2lXkE!lU(>k`0^4mJ zlhBs1^?vp_+{=iOT3iB{$dSu=#+k2b3i7 ztRqtgDq^+MPM1c7V^t>KIPzdUO&rU!hX%`XBLg{AI0BMB$B2C6)dU>N9Sl8pLj@?r z=6dTV1QtHx_x|(iTaewOwAT4kfTng?nrZn=8X`xz?}bdt92V4i2olI52$asS%us3~ zW8mfPnZfP(WAL($f0u{oAVrZ`qC~9rP%N6Pt@Z}#X}V9n2}+X!s{yM*rG~W&U3~7G zFdu6zrI-7|dWx%%;g~nN+9h*E=thNvwf|wq4G1cfc)gqcff)IK3#NXQR}a|mC*fRd zz62nf{Fajj!YKZ2vI)CT8XEqEO_P>FXIjxZzJNDAfUoDXIF1)y=;)>6*p}8(VUm`T zAcTJ*B&-{l&UEyC&+nXX&m8pe!@FV*pS29SfZIWEZ59RK^m#0ASVU& zeh+Q?6iWHtx9@Y5DBFl?y!?nsML|&g2Os!Wgz=N45z;UQt$_JptZjOkXdd|i5yWF z@9r6A7!c$pC<9`F23*jjG@5K}ZSu60KQ>kSn5R7CCE3)P)h%SXBnm-n1S1R=WiHH2 z=QN_5?7mPG%=dl2KGUa9+W0AF5cfl3q{Gy-Cq~H8r#*9^v-A4M1*+V=-oy%$>9xT6a7Ly7cn5x@B*hZ0U zBnv2}^2Y*cY?^e8)%Z%Oa@*A$g6u2!1I@Uewz>Z7lfretT ztomKr8*OKzK*94{jdCKka`N`PnDWxTnXo&|&ib+#VPz>mZN9^&VneSZ_*$WJGyjS*+-v&ca2Kzu52-O6!SOuyoQa zrg;5Q?ltFcSCLGnRb988yw`hN(SW5@{jhK`>;=oD<+y~v`b($Hy$uEUp?>_-f_%`| zbklLqD|ld9Tat48K})ZCKW8x~UBdM#oo)PjT#XoHfl?nWo^mIyE)58 zmpO~qD-qB`e$si&mw3M6I2TonMEBQUM!sb-yp%N4%1Fu|pSYNg-R~3nlt1U!>zp6- zc!_~NEKBcxzUMA&309Pq{>Op_e-VO6!nuUO(s_T35PSREtzo;p@eK4!B91~+!LJPc z^m+haw1y0y1)mQISdA#QC?H3?ydDx9-Db#9^SiV^IXVc{MtVH36j--rHrs#YgXz^9 z8Q;AMIyTPa8C)bhc`tGiOYVraLrGkgB?2QEN3(FBP;-0qcJllnR3GV4pX6V+?k8^H zrSkm`A!g%jjzQr(IRzPf`eR+cCUG_5J--?f-aMWq9Nl8X<}A09Zx2G1!E|-*V$TqB z2;?vHri+q!r0ZQ_Z9U>GH?_p(I`0wgqDVNh&9JNHIm?TqFtC7&60HMQd5jy; oikp{usgc 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 literal 0 HcmV?d00001 diff --git a/DistanceManhattan.png b/DistanceManhattan.png new file mode 100644 index 0000000000000000000000000000000000000000..0eff545df2dab8c293146ee277d9c718a1e2ea23 GIT binary patch literal 11552 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 SF0f(%0000 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 literal 0 HcmV?d00001 diff --git a/DistancePearson.png b/DistancePearson.png new file mode 100644 index 0000000000000000000000000000000000000000..67e2cbdcc14bbe6f15aac1827150af328e176093 GIT binary patch literal 3838 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 Av;Y7A literal 0 HcmV?d00001 diff --git a/DistanceSAD.png b/DistanceSAD.png new file mode 100644 index 0000000000000000000000000000000000000000..0eff545df2dab8c293146ee277d9c718a1e2ea23 GIT binary patch literal 11552 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 X${DLx&d_nZ00000NkvXXu0mjf%(s;{ literal 0 HcmV?d00001 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..72f1eba6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,85 @@ +FROM jupyter/base-notebook:latest + +# Install .NET CLI dependencies + +ARG NB_USER=fsdocs-user +ARG NB_UID=1000 +ENV USER ${NB_USER} +ENV NB_UID ${NB_UID} +ENV HOME /home/${NB_USER} + +WORKDIR ${HOME} + +USER root +RUN apt-get update +RUN apt-get install -y curl + +ENV \ + # Enable detection of running in a container + DOTNET_RUNNING_IN_CONTAINER=true \ + # Enable correct mode for dotnet watch (only mode supported in a container) + DOTNET_USE_POLLING_FILE_WATCHER=true \ + # Skip extraction of XML docs - generally not useful within an image/container - helps performance + NUGET_XMLDOC_MODE=skip \ + # Opt out of telemetry until after we install jupyter when building the image, this prevents caching of machine id + DOTNET_INTERACTIVE_CLI_TELEMETRY_OPTOUT=true + +# Install .NET CLI dependencies +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + libc6 \ + libgcc1 \ + libgssapi-krb5-2 \ + libicu66 \ + libssl1.1 \ + libstdc++6 \ + zlib1g \ + && rm -rf /var/lib/apt/lists/* + +# Install .NET Core SDK + +# When updating the SDK version, the sha512 value a few lines down must also be updated. +ENV DOTNET_SDK_VERSION 5.0.101 + +RUN dotnet_sdk_version=5.0.101 \ + && curl -SL --output dotnet.tar.gz https://dotnetcli.azureedge.net/dotnet/Sdk/$dotnet_sdk_version/dotnet-sdk-$dotnet_sdk_version-linux-x64.tar.gz \ + && dotnet_sha512='398d88099d765b8f5b920a3a2607c2d2d8a946786c1a3e51e73af1e663f0ee770b2b624a630b1bec1ceed43628ea8bc97963ba6c870d42bec064bde1cd1c9edb' \ + && echo "$dotnet_sha512 dotnet.tar.gz" | sha512sum -c - \ + && mkdir -p /usr/share/dotnet \ + && tar -ozxf dotnet.tar.gz -C /usr/share/dotnet \ + && rm dotnet.tar.gz \ + && ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet \ + # Trigger first run experience by running arbitrary cmd + && dotnet help + +# Copy notebooks + +COPY ./ ${HOME}/notebooks/ + +# Copy package sources + +COPY ./NuGet.config ${HOME}/nuget.config + +RUN chown -R ${NB_UID} ${HOME} +USER ${USER} + +#Install nteract +RUN pip install nteract_on_jupyter + +# Install lastest build from master branch of Microsoft.DotNet.Interactive +RUN dotnet tool install -g Microsoft.dotnet-interactive --add-source "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json" + +#latest stable from nuget.org +#RUN dotnet tool install -g Microsoft.dotnet-interactive --add-source "https://api.nuget.org/v3/index.json" + +ENV PATH="${PATH}:${HOME}/.dotnet/tools" +RUN echo "$PATH" + +# Install kernel specs +RUN dotnet interactive jupyter install + +# Enable telemetry once we install jupyter for the image +ENV DOTNET_INTERACTIVE_CLI_TELEMETRY_OPTOUT=false + +# Set root to notebooks +WORKDIR ${HOME}/notebooks/ \ No newline at end of file diff --git a/Euclid.html b/Euclid.html index 88d53829..c94822f5 100644 --- a/Euclid.html +++ b/Euclid.html @@ -1,63 +1,138 @@ - - - Euclid & Number Theory + +<head> + <meta charset="utf-8"> + <title>Euclid & Number Theory - - - - - - - - - - - - - - - - - - -
    -
    - -

    Math.NET Numerics

    + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    +

    Euclid & Number Theory

    The static Euclid class in the MathNet.Numerics namespace provides routines related to the domain of integers.

    Remainder vs. Canonical Modulus

    @@ -72,12 +147,7 @@ where the result of the division cannot be expressed as an integer. It is thus n that the remainder has the sign of the dividend.

    In C# and F#, the remainder is available as % operator, in VB as Mod. Alternatively you can use the Reminder function:

    - -
    1: 
    -2: 
    -3: 
    -4: 
    -
    Euclid.Remainder( 5,  3); // =  2, such that 5 = 1*3 + 2
    +
    Euclid.Remainder( 5,  3); // =  2, such that 5 = 1*3 + 2
     Euclid.Remainder(-5,  3); // = -2, such that -5 = -1*3 - 2
     Euclid.Remainder( 5, -3); // =  2, such that 5 = -1*-3 + 2
     Euclid.Remainder(-5, -3); // = -2, such that -5 = 1*-3 - 2
    @@ -89,12 +159,7 @@ when their difference is an integer multiple of n. The modulo operator normalize
     to the fundamental or smallest values congruent modulo n, where n is the divisor, and thus
     to the interval from 0 to n (including 0 but excluding n, possibly negative). It is thus natural that
     the modulus always has the sign of the divisor.

    - -
    1: 
    -2: 
    -3: 
    -4: 
    -
    Euclid.Modulus( 5,  3); // =  2, congruent modulo 3 by 5 - 1*3
    +
    Euclid.Modulus( 5,  3); // =  2, congruent modulo 3 by 5 - 1*3
     Euclid.Modulus(-5,  3); // =  1, congruent modulo 3 by -5 + 2*3
     Euclid.Modulus( 5, -3); // = -1, congruent modulo -3 by 5 + 2*-3
     Euclid.Modulus(-5, -3); // = -2, congruent modulo -3 by -5 - 1*-3
    @@ -123,13 +188,7 @@ the integer argument is a perfect square, i.e. a square of an integer.

    The GreatestCommonDivisor evaluates the GCD of either two integers or a full list or array of them using Euclid's algorithm. An extended version also returns how exactly the GCD can be composed from two integer arguments.

    - -
    1: 
    -2: 
    -3: 
    -4: 
    -5: 
    -
    Euclid.GreatestCommonDivisor(10, 15, 45); // 5
    +
    Euclid.GreatestCommonDivisor(10, 15, 45); // 5
     
     long x, y;
     Euclid.ExtendedGreatestCommonDivisor(45, 18, out x, out y) // 9
    @@ -137,93 +196,19 @@ Euclid.ExtendedGreatestCommonDivisor(45, 
     

    Least Common Multiple

    Closely related to the GCD, LeastCommonMultiple returns the LCM of two or more integers.

    - -
    1: 
    -
    Euclid.LeastCommonMultiple(3, 5, 6); // 30
    +
    Euclid.LeastCommonMultiple(3, 5, 6); // 30
     
    - - -
    - -
    - + - + + + + + + + + + + diff --git a/Functions.html b/Functions.html index 5106963f..8b07633b 100644 --- a/Functions.html +++ b/Functions.html @@ -1,63 +1,138 @@ - - - Special Functions + +<head> + <meta charset="utf-8"> + <title>Special Functions - - - + + + + + + - - - - + - - - - - + + + + + + + + + + + + - - - -
    -
    - -

    Math.NET Numerics

    + + +
    + +
    +
    +

    Special Functions

    All the following special functions are available in the static SpecialFunctions class:

    Factorial

      @@ -65,10 +140,7 @@

    \[x \mapsto x! = \prod_{k=1}^{x} k = \Gamma(x+1)\]

    Code Sample:

    - -
    1: 
    -2: 
    -
    double x = SpecialFunctions.Factorial(14); // 87178291200.0
    +
    double x = SpecialFunctions.Factorial(14); // 87178291200.0
     double y = SpecialFunctions.Factorial(31); // 8.2228386541779224E+33
     
      @@ -186,9 +258,7 @@

      Inverse \(x\) of the complementary Error function, such that \(\mathrm{erfc}(x) = z\).

      \[z \mapsto \mathrm{erfc}^{-1}(z)\]

      Code Sample:

      - -
      1: 
      -
      double erf = SpecialFunctions.Erf(0.9); // 0.7969082124
      +
      double erf = SpecialFunctions.Erf(0.9); // 0.7969082124
       

      Sigmoid: Logistic function

        @@ -307,88 +377,16 @@ for both real and complex arguments.

      • Conversion routines between radian, degree and grad.
      - - -
      - -
      - + - + + + + + + + + + + diff --git a/Generate.html b/Generate.html index f7a3fd99..f8483f37 100644 --- a/Generate.html +++ b/Generate.html @@ -1,63 +1,138 @@ - - - Generating Data + +<head> + <meta charset="utf-8"> + <title>Generating Data - - - + + + + + + - - - - + - - - - - + + + + + + + + + + + + - - - -
      -
      - -

      Math.NET Numerics

      + + +
      + +
      +
      +

      Generating Data

      Numerics is all about analyzing and manipulating numeric data. But unless you can read in data from an external file, source or e.g. with the excellent F# Type Providers, you may need to generate synthetic or random data locally, or transform existing data into a new form. @@ -70,23 +145,13 @@ This is intended for simplicity and consistency between array and sequence opera and either a provided step or a step of 1.0. Linear range is equivalent to the single colon : and double colon :: operators in MATLAB.

      F# has built in linear range support in array comprehensions with the colon operator:

      - - - -
      1: 
      -2: 
      -3: 
      -4: 
      -
      [ 10.0 .. 2.0 .. 15.0 ]
      +
      [ 10.0 .. 2.0 .. 15.0 ]
       val it : float list = [10.0; 12.0; 14.0] 
      -[ for x in 10.0 .. 2.0 .. 15.0 -> sin x ]
      +[ for x in 10.0 .. 2.0 .. 15.0 -> sin x ]
       val it : float list = [-0.5440211109; -0.536572918; 0.9906073557] 
      -
      +

      In C# you can get the same result with LinearRange:

      - -
      1: 
      -2: 
      -
      Generate.LinearRange(10, 2, 15); // returns array { 10.0, 12.0, 14.0 }
      +
      Generate.LinearRange(10, 2, 15); // returns array { 10.0, 12.0, 14.0 }
       Generate.LinearRangeMap(10, 2, 15, Math.Sin); // applies sin(x) to each value
       

      Most of the routines in the Generate class have variants with a Map suffix. @@ -98,32 +163,19 @@ lazy enumerable sequences instead of arrays.

      Generates a linearly or log-spaced array within an interval, but other than linear range where the step is provided, here we instead provide the number of values we want. This is equivalent to the linspace and logspace operators in MATLAB.

      - -
      1: 
      -2: 
      -
      Generate.LinearSpaced(11, 0.0, 1.0); // returns array { 0.0, 0.1, 0.2, .., 1.0 }
      +
      Generate.LinearSpaced(11, 0.0, 1.0); // returns array { 0.0, 0.1, 0.2, .., 1.0 }
       Generate.LinearSpacedMap(15, 0.0, Math.Pi, Math.Sin); // applies sin(x) to each value
       

      In F# you can also use:

      - - - -
      1: 
      -2: 
      -3: 
      -4: 
      -5: 
      -
      Generate.linearSpacedMap 15 0.0 Math.PI sin
      +
      Generate.linearSpacedMap 15 0.0 Math.PI sin
       val it : float [] = 
         [|0.0; 0.222520934; 0.4338837391; 0.6234898019; 0.7818314825; 0.9009688679; 
           0.9749279122; 1.0; 0.9749279122; 0.9009688679; 0.7818314825; 0.6234898019; 
           0.4338837391; 0.222520934; 1.224606354e-16|] 
      -
      +

      LogSpaced works the same way but instead of the values \(10^x\) it spaces the decade exponents \(x\) linearly between the provided two exponents.

      - -
      1: 
      -
      Generate.LogSpaced(4,0,3); // returns array { 1, 10, 100, 1000 }
      +
      Generate.LogSpaced(4,0,3); // returns array { 1, 10, 100, 1000 }
       

      Kronecker Delta Impulse

      The Kronecker delta \(\delta[n]\) is a fundamental signal in time-discrete signal processing, @@ -134,20 +186,12 @@ It is closely related to the Dirac delta impulse function \(\ parameter \(d\) and amplitude \(A\) such that the resulting generated signal is

      \[s[n] = A\cdot\delta[n-d] = \begin{cases} 0 &\mbox{if } n \ne d \\ A & \mbox{if } n = d\end{cases}\]

      There is also a periodic version in PeriodicImpulse which accepts an additional period parameter.

      - - - -
      1: 
      -2: 
      -3: 
      -4: 
      -5: 
      -
      Generate.Impulse(8, 2.0, 3)
      +
      Generate.Impulse(8, 2.0, 3)
       val it : float [] = [|0.0; 0.0; 0.0; 2.0; 0.0; 0.0; 0.0; 0.0|] 
       
      -Generate.PeriodicImpulse(8, 3, 10.0, 1)
      +Generate.PeriodicImpulse(8, 3, 10.0, 1)
       val it : float [] = [|0.0; 10.0; 0.0; 0.0; 10.0; 0.0; 0.0; 10.0|] 
      -
      +

      Heaviside Step

      Another fundamental signal in signal processing, the Heaviside step function \(H[n]\) is the integral of the Dirac delta impulse and represents a signal that switches on @@ -156,14 +200,9 @@ at a specified time and then stays on indefinitely. In discrete time:

      The Step routines generates a Heaviside step, but just like the Kronecker Delta impulse also accepts a sample delay parameter \(d\) and amplitude \(A\) such that the resulting generated signal is

      \[s[n] = A\cdot H[n-d] = \begin{cases} 0 &\mbox{if } n < d \\ A & \mbox{if } n \ge d\end{cases}\]

      - - - -
      1: 
      -2: 
      -
      Generate.Step(8, 2.0, 3)
      +
      Generate.Step(8, 2.0, 3)
       val it : float [] = [|0.0; 0.0; 0.0; 2.0; 2.0; 2.0; 2.0; 2.0|] 
      -
      +

      Periodic Sawtooth

      Generates an array of the given length with a periodic upper forward sawtooth signal, i.e. a line starting at zero up to some amplitude \(A\), then drop back to zero instantly and start afresh. @@ -190,36 +229,24 @@ The circumference of the circle. Typically \(1\) or Delay: Optional initial delay, in samples. Contributes to \(\theta\).

      The equivalent map function accepts a custom map lambda as second argument after the length:

      - - - -
      1: 
      -2: 
      -3: 
      -4: 
      -
      Generate.periodicMap 15 ((+) 100.0) 1000.0 100.0 10.0 0.0 0
      +
      Generate.periodicMap 15 ((+) 100.0) 1000.0 100.0 10.0 0.0 0
       val it : float [] = 
         [|100.0; 101.0; 102.0; 103.0; 104.0; 105.0; 106.0; 107.0; 108.0; 109.0; 
           100.0; 101.0; 102.0; 103.0; 104.0|] 
      -
      +

      Sinusoidal

      Generates a Sine wave array of the given length. This is equivalent to applying a scaled trigonometric Sine function to a periodic sawtooth of amplitude \(2\pi\).

      \[s(x) = A\cdot\sin(2\pi\nu x + \theta)\]

      Generate.Sinusoidal(length,samplingRate,frequency,amplitude,mean,phase,delay)

      - -
      1: 
      -2: 
      -
      Generate.Sinusoidal(15, 1000.0, 100.0, 10.0);
      +
      Generate.Sinusoidal(15, 1000.0, 100.0, 10.0);
       // returns array { 0, 5.9, 9.5, 9.5, 5.9, 0, -5.9, ... }
       

      Random

      Generate random sequences by sampling from a random distribution.

      Uniform Distribution

      Generate sample sequences distributed uniformly between 0 and 1.

      - -
      1: 
      -
      Generate.Uniform(100); // e.g. 0.867421787170424, 0.236744313145403, ... 
      +
      Generate.Uniform(100); // e.g. 0.867421787170424, 0.236744313145403, ... 
       

      Uniform supports mapping to functions with not only one but also two uniform variables as arguments, with UniformMap and UniformMap2. As usual, lazy sequences can be @@ -235,142 +262,55 @@ from. See the section about random numbers and probability distributions for det

      Map

      Generates a new array or sequence where each new values is the result of applying the provided function the the corresponding value in the input data.

      - -
      1: 
      -2: 
      -
      var a = new double[] { 2.0, 4.0, 3.0, 6.0 };
      +
      var a = new double[] { 2.0, 4.0, 3.0, 6.0 };
       Generate.Map(a, x => x + 1.0); // returns array { 3.0, 5.0, 4.0, 7.0 }
       

      In F# you'd typically use the Array module to the same effect (and should continue to do so):

      - - - -
      1: 
      -2: 
      -
      Array.map ((+) 1.0) a
      +
      Array.map ((+) 1.0) a
       val it : float [] = [|3.0; 5.0; 4.0; 7.0|] 
      -
      +

      ...but no equivalent operation is available in the .NET base class libraries (BCL) for C#. You can use LINQ, but that operates on sequences instead of arrays:

      - -
      1: 
      -
      a.Select(x => x + 1.0).ToArray();
      +
      a.Select(x => x + 1.0).ToArray();
       

      Similarly, with Map2 you can also map a function accepting two inputs to two input arrays:

      - - - -
      1: 
      -2: 
      -3: 
      -
      let b = [| 1.0; -1.0; 2.0; -2.0 |]
      -Generate.Map2(a, b, fun x y -> x + y)
      +
      let b = [| 1.0; -1.0; 2.0; -2.0 |]
      +Generate.Map2(a, b, fun x y -> x + y)
       val it : float [] = [|3.0; 3.0; 5.0; 4.0|] 
      -
      +

      Typical F# equivalent:

      - - - -
      1: 
      -2: 
      -
      Array.map2 (+) a b
      +
      Array.map2 (+) a b
       val it : float [] = [|3.0; 3.0; 5.0; 4.0|] 
      -
      +

      And in C# with LINQ:

      - -
      1: 
      -
      a.Zip(b, (x, y) => x + y).ToArray();
      +
      a.Zip(b, (x, y) => x + y).ToArray();
       
      -
      val x : float
      -
      val sin : value:'T -> 'T (requires member Sin)

      Full name: Microsoft.FSharp.Core.Operators.sin
      -
      module Array

      from Microsoft.FSharp.Collections
      -
      val map : mapping:('T -> 'U) -> array:'T [] -> 'U []

      Full name: Microsoft.FSharp.Collections.Array.map
      -
      val a : float []

      Full name: Generate.a
      -
      val b : float []

      Full name: Generate.b
      -
      val map2 : mapping:('T1 -> 'T2 -> 'U) -> array1:'T1 [] -> array2:'T2 [] -> 'U []

      Full name: Microsoft.FSharp.Collections.Array.map2
      +
      val x : float
      +
      val sin : value:'T -> 'T (requires member Sin)
      <summary>Sine of the given number</summary>
      <param name="value">The input value.</param>
      <returns>The sine of the input.</returns>
      +
      Modul Array -
      -
      -
      +
      val map : mapping:('T -> 'U) -> array:'T [] -> 'U []
      <summary>Builds a new array whose elements are the results of applying the given function + to each of the elements of the array.</summary>
      <param name="mapping">The function to transform elements of the array.</param>
      <param name="array">The input array.</param>
      <returns>The array of transformed elements.</returns>
      <exception cref="T:System.ArgumentNullException">Thrown when the input array is null.</exception>
      +
      val a : float []
      +
      val b : float []
      +
      val map2 : mapping:('T1 -> 'T2 -> 'U) -> array1:'T1 [] -> array2:'T2 [] -> 'U []
      <summary>Builds a new collection whose elements are the results of applying the given function + to the corresponding elements of the two collections pairwise. The two input + arrays must have the same lengths, otherwise an <c>ArgumentException</c> is + raised.</summary>
      <param name="mapping">The function to transform the pairs of the input elements.</param>
      <param name="array1">The first input array.</param>
      <param name="array2">The second input array.</param>
      <exception cref="T:System.ArgumentException">Thrown when the input arrays differ in length.</exception>
      <exception cref="T:System.ArgumentNullException">Thrown when either of the input arrays is null.</exception>
      <returns>The array of transformed elements.</returns>
      - -
    • Linear Equation Systems
    • -
    • Nonlinear Root Finding
    • - - -
    • Linear Least Squares
    • -
    • Nonlinear Optimization
    • -
    • Distance Metrics
    • - - -
    • Regression
    • -
    • Interpolation
    • -
    • Fourier Approximation
    • - - -
    • Intel MKL
    • - - -
    • Delimited Text Files (CSV)
    • -
    • NIST MatrixMarket
    • -
    • MATLAB
    • -
    • IF# Notebook
    • -
    • FsLab & Deedle
    • -
    • Microsoft Excel
    • -
    • numl.net machine learning
    • -
    • R-project
    • - - - - - + + + + + + + + + + diff --git a/IFsharpNotebook.html b/IFsharpNotebook.html index 5642156b..6870a325 100644 --- a/IFsharpNotebook.html +++ b/IFsharpNotebook.html @@ -1,63 +1,138 @@ - - - IF# Notebook + +<head> + <meta charset="utf-8"> + <title>IF# Notebook - - - + + + + + + - - - - + - - - - - + + + + + + + + + + + + - - - -
      -
      - -

      Math.NET Numerics

      + + +
      + +
      +
      +

      IF# Notebook

      iPython provides a rich browser-based interactive notebook with support for code, text, mathematical expressions, inline plots and other rich media. IfSharp, developed by Bayard Rock, is an F# profile for iPython with IntelliSense and embedded FSharp.Charting. Thanks to its NuGet support it can load other packages like Math.NET Numerics on demand.

      @@ -80,216 +155,146 @@ Since v3.3 the Math.NET Numerics F# package includes a script MathNet.Nume Unfortunately loading this script requires the exact version in the path - if you know a way to avoid this please let us know.

      Screenshot

      Alternatively you can also use the code below and adapt it to your needs, e.g. if you want it to show more rows.

      - - - -
       1: 
      - 2: 
      - 3: 
      - 4: 
      - 5: 
      - 6: 
      - 7: 
      - 8: 
      - 9: 
      -10: 
      -11: 
      -12: 
      -13: 
      -14: 
      -15: 
      -16: 
      -17: 
      -18: 
      -19: 
      -20: 
      -21: 
      -22: 
      -23: 
      -24: 
      -25: 
      -26: 
      -27: 
      -28: 
      -29: 
      -30: 
      -31: 
      -32: 
      -33: 
      -34: 
      -35: 
      -36: 
      -37: 
      -38: 
      -39: 
      -40: 
      -41: 
      -42: 
      -43: 
      -44: 
      -45: 
      -46: 
      -
      open MathNet.Numerics.LinearAlgebra
      +
      open MathNet.Numerics.LinearAlgebra
       
      -let inline (|Float|_|) (v:obj) =
      -    if v :? float then Some(v :?> float) else None
      -let inline (|Float32|_|) (v:obj) =
      -    if v :? float32 then Some(v :?> float32) else None
      -let inline (|PositiveInfinity|_|) (v: ^T) =
      -    if (^T : (static member IsPositiveInfinity: 'T -> bool) (v))
      -    then Some PositiveInfinity else None
      -let inline (|NegativeInfinity|_|) (v: ^T) =
      -    if (^T : (static member IsNegativeInfinity: 'T -> bool) (v))
      -    then Some NegativeInfinity else None
      -let inline (|NaN|_|) (v: ^T) =
      -    if (^T : (static member IsNaN: 'T -> bool) (v))
      -    then Some NaN else None
      +let inline (|Float|_|) (v:obj) =
      +    if v :? float then Some(v :?> float) else None
      +let inline (|Float32|_|) (v:obj) =
      +    if v :? float32 then Some(v :?> float32) else None
      +let inline (|PositiveInfinity|_|) (v: ^T) =
      +    if (^T : (static member IsPositiveInfinity: 'T -> bool) (v))
      +    then Some PositiveInfinity else None
      +let inline (|NegativeInfinity|_|) (v: ^T) =
      +    if (^T : (static member IsNegativeInfinity: 'T -> bool) (v))
      +    then Some NegativeInfinity else None
      +let inline (|NaN|_|) (v: ^T) =
      +    if (^T : (static member IsNaN: 'T -> bool) (v))
      +    then Some NaN else None
       
      -let inline formatMathValue (floatFormat:string) = function
      -  | PositiveInfinity -> "\\infty"
      -  | NegativeInfinity -> "-\\infty"
      -  | NaN -> "\\times"
      -  | Float v -> v.ToString(floatFormat)
      -  | Float32 v -> v.ToString(floatFormat)
      -  | v -> v.ToString()
      +let inline formatMathValue (floatFormat:string) = function
      +  | PositiveInfinity -> "\\infty"
      +  | NegativeInfinity -> "-\\infty"
      +  | NaN -> "\\times"
      +  | Float v -> v.ToString(floatFormat)
      +  | Float32 v -> v.ToString(floatFormat)
      +  | v -> v.ToString()
       
      -let inline formatMatrix (matrix: Matrix<'T>) =
      -  String.concat Environment.NewLine
      -    [ "\\begin{bmatrix}"
      -      matrix.ToMatrixString(10,4,7,2,"\\cdots","\\vdots","\\ddots",
      -        " & ", "\\\\ " + Environment.NewLine, (fun x -> formatMathValue "G4" x))
      -      "\\end{bmatrix}" ]
      +let inline formatMatrix (matrix: Matrix<'T>) =
      +  String.concat Environment.NewLine
      +    [ "\\begin{bmatrix}"
      +      matrix.ToMatrixString(10,4,7,2,"\\cdots","\\vdots","\\ddots",
      +        " & ", "\\\\ " + Environment.NewLine, (fun x -> formatMathValue "G4" x))
      +      "\\end{bmatrix}" ]
       
      -let inline formatVector (vector: Vector<'T>) =
      -  String.concat Environment.NewLine
      -    [ "\\begin{bmatrix}"
      -      vector.ToVectorString(12, 80, "\\vdots", " & ", "\\\\ " + Environment.NewLine,
      -        (fun x -> formatMathValue "G4" x))
      -      "\\end{bmatrix}" ]
      +let inline formatVector (vector: Vector<'T>) =
      +  String.concat Environment.NewLine
      +    [ "\\begin{bmatrix}"
      +      vector.ToVectorString(12, 80, "\\vdots", " & ", "\\\\ " + Environment.NewLine,
      +        (fun x -> formatMathValue "G4" x))
      +      "\\end{bmatrix}" ]
       
      -App.AddDisplayPrinter (fun (x:Matrix<float>) ->
      -    { ContentType = "text/latex"; Data = formatMatrix x })
      -App.AddDisplayPrinter (fun (x:Matrix<float32>) ->
      -    { ContentType = "text/latex"; Data = formatMatrix x })
      -App.AddDisplayPrinter (fun (x:Vector<float>) ->
      -    { ContentType = "text/latex"; Data = formatVector x })
      -App.AddDisplayPrinter (fun (x:Vector<float32>) ->
      -    { ContentType = "text/latex"; Data = formatVector x })
      -
      +App.AddDisplayPrinter (fun (x:Matrix<float>) -> + { ContentType = "text/latex"; Data = formatMatrix x }) +App.AddDisplayPrinter (fun (x:Matrix<float32>) -> + { ContentType = "text/latex"; Data = formatMatrix x }) +App.AddDisplayPrinter (fun (x:Vector<float>) -> + { ContentType = "text/latex"; Data = formatVector x }) +App.AddDisplayPrinter (fun (x:Vector<float32>) -> + { ContentType = "text/latex"; Data = formatVector x }) +
      -
      val v : obj
      -
      type obj = System.Object

      Full name: Microsoft.FSharp.Core.obj
      -
      Multiple items
      val float : value:'T -> float (requires member op_Explicit)

      Full name: Microsoft.FSharp.Core.Operators.float

      --------------------
      type float = System.Double

      Full name: Microsoft.FSharp.Core.float

      --------------------
      type float<'Measure> = float

      Full name: Microsoft.FSharp.Core.float<_>
      -
      union case Option.Some: Value: 'T -> Option<'T>
      -
      union case Option.None: Option<'T>
      -
      Multiple items
      val float32 : value:'T -> float32 (requires member op_Explicit)

      Full name: Microsoft.FSharp.Core.Operators.float32

      --------------------
      type float32 = System.Single

      Full name: Microsoft.FSharp.Core.float32

      --------------------
      type float32<'Measure> = float32

      Full name: Microsoft.FSharp.Core.float32<_>
      -
      val v : 'T (requires member IsPositiveInfinity)
      -
      type bool = System.Boolean

      Full name: Microsoft.FSharp.Core.bool
      -
      val v : 'T (requires member IsNegativeInfinity)
      -
      val v : 'T (requires member IsNaN)
      -
      val formatMathValue : floatFormat:string -> _arg1:'a -> string (requires member IsNaN and member IsPositiveInfinity and member IsNegativeInfinity)

      Full name: IFsharpNotebook.formatMathValue
      -
      val floatFormat : string
      -
      Multiple items
      val string : value:'T -> string

      Full name: Microsoft.FSharp.Core.Operators.string

      --------------------
      type string = System.String

      Full name: Microsoft.FSharp.Core.string
      -
      active recognizer PositiveInfinity: 'T -> unit option

      Full name: IFsharpNotebook.( |PositiveInfinity|_| )
      -
      active recognizer NegativeInfinity: 'T -> unit option

      Full name: IFsharpNotebook.( |NegativeInfinity|_| )
      -
      active recognizer NaN: 'T -> unit option

      Full name: IFsharpNotebook.( |NaN|_| )
      -
      active recognizer Float: obj -> float option

      Full name: IFsharpNotebook.( |Float|_| )
      -
      val v : float
      -
      System.Double.ToString() : string
      System.Double.ToString(provider: System.IFormatProvider) : string
      System.Double.ToString(format: string) : string
      System.Double.ToString(format: string, provider: System.IFormatProvider) : string
      -
      active recognizer Float32: obj -> float32 option

      Full name: IFsharpNotebook.( |Float32|_| )
      -
      val v : float32
      -
      System.Single.ToString() : string
      System.Single.ToString(format: string) : string
      System.Single.ToString(provider: System.IFormatProvider) : string
      System.Single.ToString(format: string, provider: System.IFormatProvider) : string
      -
      val v : 'a (requires member IsNaN and member IsPositiveInfinity and member IsNegativeInfinity)
      -
      System.Object.ToString() : string
      -
      val formatMatrix : matrix:'a -> string

      Full name: IFsharpNotebook.formatMatrix
      -
      val matrix : 'a
      -
      module String

      from Microsoft.FSharp.Core
      -
      val concat : sep:string -> strings:seq<string> -> string

      Full name: Microsoft.FSharp.Core.String.concat
      -
      val formatVector : vector:'a -> string

      Full name: IFsharpNotebook.formatVector
      -
      val vector : 'a
      -
      namespace Microsoft.FSharp.Data
      +
      val v : obj
      +
      type obj = System.Object
      <summary>An abbreviation for the CLI type <see cref="T:System.Object" />.</summary>
      <category>Basic Types</category>
      +
      Multiple items
      val float : value:'T -> float (requires member op_Explicit)
      <summary>Converts the argument to 64-bit float. This is a direct conversion for all + primitive numeric types. For strings, the input is converted using <c>Double.Parse()</c> + with InvariantCulture settings. Otherwise the operation requires an appropriate + static conversion method on the input type.</summary>
      <param name="value">The input value.</param>
      <returns>The converted float</returns>


      --------------------
      [<Struct>] +type float = System.Double
      <summary>An abbreviation for the CLI type <see cref="T:System.Double" />.</summary>
      <category>Basic Types</category>


      --------------------
      type float<'Measure> = + float
      <summary>The type of double-precision floating point numbers, annotated with a unit of measure. + The unit of measure is erased in compiled code and when values of this type + are analyzed using reflection. The type is representationally equivalent to + <see cref="T:System.Double" />.</summary>
      <category index="6">Basic Types with Units of Measure</category>
      +
      Union-Fall Option.Some: Value: 'T -> Option<'T>
      <summary>The representation of "Value of type 'T"</summary>
      <param name="Value">The input value.</param>
      <returns>An option representing the value.</returns>
      +
      Union-Fall Option.None: Option<'T>
      <summary>The representation of "No value"</summary>
      +
      Multiple items
      val float32 : value:'T -> float32 (requires member op_Explicit)
      <summary>Converts the argument to 32-bit float. This is a direct conversion for all + primitive numeric types. For strings, the input is converted using <c>Single.Parse()</c> + with InvariantCulture settings. Otherwise the operation requires an appropriate + static conversion method on the input type.</summary>
      <param name="value">The input value.</param>
      <returns>The converted float32</returns>


      --------------------
      [<Struct>] +type float32 = System.Single
      <summary>An abbreviation for the CLI type <see cref="T:System.Single" />.</summary>
      <category>Basic Types</category>


      --------------------
      type float32<'Measure> = + float32
      <summary>The type of single-precision floating point numbers, annotated with a unit of measure. + The unit of measure is erased in compiled code and when values of this type + are analyzed using reflection. The type is representationally equivalent to + <see cref="T:System.Single" />. + </summary>
      <category>Basic Types with Units of Measure</category>
      +
      val v : 'T (requires member IsPositiveInfinity)
      +
      [<Struct>] +type bool = System.Boolean
      <summary>An abbreviation for the CLI type <see cref="T:System.Boolean" />.</summary>
      <category>Basic Types</category>
      +
      val v : 'T (requires member IsNegativeInfinity)
      +
      val v : 'T (requires member IsNaN)
      +
      val formatMathValue : floatFormat:string -> _arg1:'a -> string (requires member IsNaN and member IsPositiveInfinity and member IsNegativeInfinity)
      +
      val floatFormat : string
      +
      Multiple items
      val string : value:'T -> string
      <summary>Converts the argument to a string using <c>ToString</c>.</summary>
      <remarks>For standard integer and floating point values the and any type that implements <c>IFormattable</c><c>ToString</c> conversion uses <c>CultureInfo.InvariantCulture</c>. </remarks>
      <param name="value">The input value.</param>
      <returns>The converted string.</returns>


      --------------------
      type string = System.String
      <summary>An abbreviation for the CLI type <see cref="T:System.String" />.</summary>
      <category>Basic Types</category>
      +
      aktive Erkennung PositiveInfinity: 'T -> unit option
      +
      aktive Erkennung NegativeInfinity: 'T -> unit option
      +
      aktive Erkennung NaN: 'T -> unit option
      +
      aktive Erkennung Float: obj -> float option
      +
      val v : float
      +
      System.Double.ToString() : string
      System.Double.ToString(format: string) : string
      System.Double.ToString(provider: System.IFormatProvider) : string
      System.Double.ToString(format: string, provider: System.IFormatProvider) : string
      +
      aktive Erkennung Float32: obj -> float32 option
      +
      val v : float32
      +
      System.Single.ToString() : string
      System.Single.ToString(format: string) : string
      System.Single.ToString(provider: System.IFormatProvider) : string
      System.Single.ToString(format: string, provider: System.IFormatProvider) : string
      +
      val v : 'a (requires member IsNaN and member IsPositiveInfinity and member IsNegativeInfinity)
      +
      System.Object.ToString() : string
      +
      val formatMatrix : matrix:'a -> string
      +
      val matrix : 'a
      +
      Modul String -
      -
      -
      +
      val concat : sep:string -> strings:seq<string> -> string
      <summary>Returns a new string made by concatenating the given strings + with separator <c>sep</c>, that is <c>a1 + sep + ... + sep + aN</c>.</summary>
      <param name="sep">The separator string to be inserted between the strings + of the input sequence.</param>
      <param name="strings">The sequence of strings to be concatenated.</param>
      <returns>A new string consisting of the concatenated strings separated by + the separation string.</returns>
      <exception cref="T:System.ArgumentNullException">Thrown when <c>strings</c> is null.</exception>
      +
      val formatVector : vector:Vector<'T> -> string (requires default constructor and value type and 'T :> System.ValueType)
      +
      val vector : Vector<'T> (requires default constructor and value type and 'T :> System.ValueType)
      +
      Multiple items
      type Vector = + static member Abs<'T (requires default constructor and value type and 'T :> ValueType)> : value: Vector<'T> -> Vector<'T> + static member Add<'T (requires default constructor and value type and 'T :> ValueType)> : left: Vector<'T> * right: Vector<'T> -> Vector<'T> + static member AndNot<'T (requires default constructor and value type and 'T :> ValueType)> : left: Vector<'T> * right: Vector<'T> -> Vector<'T> + static member AsVectorByte<'T (requires default constructor and value type and 'T :> ValueType)> : value: Vector<'T> -> Vector<byte> + static member AsVectorDouble<'T (requires default constructor and value type and 'T :> ValueType)> : value: Vector<'T> -> Vector<float> + static member AsVectorInt16<'T (requires default constructor and value type and 'T :> ValueType)> : value: Vector<'T> -> Vector<int16> + static member AsVectorInt32<'T (requires default constructor and value type and 'T :> ValueType)> : value: Vector<'T> -> Vector<int> + static member AsVectorInt64<'T (requires default constructor and value type and 'T :> ValueType)> : value: Vector<'T> -> Vector<int64> + static member AsVectorSByte<'T (requires default constructor and value type and 'T :> ValueType)> : value: Vector<'T> -> Vector<sbyte> + static member AsVectorSingle<'T (requires default constructor and value type and 'T :> ValueType)> : value: Vector<'T> -> Vector<float32> + ...
      <summary>Provides a collection of static convenience methods for creating, manipulating, combining, and converting generic vectors.</summary>

      --------------------
      [<Struct>] +type Vector<'T (requires default constructor and value type and 'T :> ValueType)> = + new : values: ReadOnlySpan<byte> -> unit + 5 Überladungen + member CopyTo : destination: Span<byte> -> unit + 3 Überladungen + member Equals : other: Vector<'T> -> bool + 1 Überladung + member GetHashCode : unit -> int + member ToString : unit -> string + 2 Überladungen + member TryCopyTo : destination: Span<byte> -> bool + 1 Überladung + static member op_Addition : left: Vector<'T> * right: Vector<'T> -> Vector<'T> + static member op_BitwiseAnd : left: Vector<'T> * right: Vector<'T> -> Vector<'T> + static member op_BitwiseOr : left: Vector<'T> * right: Vector<'T> -> Vector<'T> + static member op_Division : left: Vector<'T> * right: Vector<'T> -> Vector<'T> + ...
      <summary>Represents a single vector of a specified numeric type that is suitable for low-level optimization of parallel algorithms.</summary>
      <typeparam name="T">The vector type. <c>T</c> can be any primitive numeric type.</typeparam>


      --------------------
      Vector ()
      Vector(values: System.ReadOnlySpan<byte>) : Vector<'T>
      Vector(values: System.ReadOnlySpan<'T>) : Vector<'T>
      Vector(values: System.Span<'T>) : Vector<'T>
      Vector(value: 'T) : Vector<'T>
      Vector(values: 'T []) : Vector<'T>
      Vector(values: 'T [], index: int) : Vector<'T>
      +
      Namespace Microsoft.FSharp.Data
      - -
    • Linear Equation Systems
    • -
    • Nonlinear Root Finding
    • - - -
    • Linear Least Squares
    • -
    • Nonlinear Optimization
    • -
    • Distance Metrics
    • - - -
    • Regression
    • -
    • Interpolation
    • -
    • Fourier Approximation
    • - - -
    • Intel MKL
    • - - -
    • Delimited Text Files (CSV)
    • -
    • NIST MatrixMarket
    • -
    • MATLAB
    • -
    • IF# Notebook
    • -
    • FsLab & Deedle
    • -
    • Microsoft Excel
    • -
    • numl.net machine learning
    • -
    • R-project
    • - - - - - + + + + + + + + + + diff --git a/IfSharp-GenerateIS.png b/IfSharp-GenerateIS.png new file mode 100644 index 0000000000000000000000000000000000000000..a4219dd02395fc28c0f2af649509a4bb5be4cabd GIT binary patch literal 31942 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
      >dJj@HJ41q4$mzZSS%)NQ#~JrLUUBa6$Z!t_ z(eBF{ke8XECZzd8-cP!mj}c6_;f=jyBD2+Y`guC~IZ>hga%U$!J!c(XPG{5Np>+7z ziPr_^&17*ezJ}S;*cIl`_8}RqQxO|;r{-RrS>*2>={#%n9odykk+t2c>kcUafL!Lk zvZ&-m|J9-%<>)4p*K=wRH7faAfBT@UF)m^EtftP=qHBz}2F{LigWge6+dYlM%81Kz z*6Cnx-%!|;{Ouji8>_gjp3l@S_%Q}J)+6Jy}Ve%V8S-&>UF^fT>j{Jv$6M8ysNRlM?F1~LEt zcb*2;pRcOlW}KIIj5&O0S^2Kn7?nE^Q)p8F-Dz(xA&C>6Ip95TPz!7Opb7oMWIMm# zSvVKu`-*s)nf>K_qP_{;QMLW*18OXCU$vz1x8!6Ql!|D@E6A{Kbe-5ZDLEQ%$SvCd zvY&X%pq9g}E(jTFUfFDtv{unLF?NqiC`P8A5sawb*SJNi?k~EH@6iZ`XvU z?9U{O?c?8hia^cqnh z_*5T+En%%3edcFu(md7(3wt@l{Q`8?mZa)R`TT~iC~tp0HiX5|*vLjfZG7zYtTN<= z`2 zdl3`-V9pn1ww2vy3?J4?RC#T|2^(TkcN|P>ER}bcvc_VZ>aGUGU+3K6H-t0pqZ>?+ zVixQ8T_Nhvbi~nowTC)`3-P_NJ+57~X6vECOe06+Rp0v0+An|VcsPnUx5o3=_U=e5 zo5XS#G=+c5NUh>&Xc^__v)>)Rk!xa34v8OZk2^KzPysaf<4V3$ziX0FEV3)5`8O8c z24-4U^UP>p9y-c=zHf4^V>z4OjnJ&2n0;%9sBl+tX6MaL`3n_fKFmXH)*FJfwZ@8* z^=Edf<6$@oGJEwx6+);)try;$1D(;jSd~>`Q^rQzMx$HZ_i^WK)7pFt8c(YfFX?d0 z3ME6k2QlL1v)bqsCC4q*w+SdusMB(L7`r~luvjRaqTZji4dtLwPSbi3BGVf7Emon6 z;R$KFi+bH)kmV|&p_d@xOGm3A-QPDBAaBWTR zkNJIaUs`y=trw*x;J319=im} zUlw8&6D*unMkBAE#84qoPz1Hx%G0B} z*ULxkw%?hWt|GSHWN3QIXrLFmH^?tteg{4fTP8mfG1Qc-As^ zPjL=91)fDee`<@t6PfN85j+s*a^rZ9O?;%e=$Sa zNrdH~v4JS(Z_#KSpT&57D^1Ta0Y)dTlU?&9PMaY#Gn@N>hF2s$U&(FuFjOML?tf`s z-eS(LT^~sk)(#S!EaNlna5@^tUb=VQ3g5WLZjkwcl^fg>);oS6+X2XD-j7OIOqXha z57ycX4{=lKLpmjzV*mI%DOUW#cOM03l2LnVkaDK}fc3&~?r7 zMW=?Iz3uU`W8~!rPpZZ6eGSSYyV@EzYvzbpfYs9_}-iI<>3lBwO9_ zIZ2)&5oaW^TZ@eMT+=3tA=j7l#!1r7xbu~{5FBzMTd8EfhL=3H)E55;tecj#bxu|m z#8%U+fx@+K0{#|RA2VDxRdIUG(W3)p5|>*!!Zlhn^?1SFmUt{}βT8;@Ui5p*d zAzOF;_PNC!@l)O(Pt>s4gT(?i46$8XUOR4Ae|og@!GW`8M;P+Aa63-oLp=pAbBfN$ zc2aT&wm*?0K=&_uAye@FC;uqw#zMWmPEtJa|B2QalZzoBe|+5|aTSyO@#~0~6NSWH zGW#O{AO;gMOTByK7Cu6I{zl?Aar|N9H%#gE##&9TdZ^~we6KnCXTY8PzAORP9BLik0%Tq+6P7nh$_;L58Y6AXMa{H{<97U zG=vRaORh5USOcEw?lNRMl!07d>J8|&`%ktOFZwGGFvB|t!tPM^iFy(N!{kbtiie3f zk0@gU&-N#;&0vvZB=35Esqz2-r)Y>mIqWarNosBuyI$ z`N@Byj)tJ>V%+bV!{Jt&guj;c(YQJuSiE96fitsfmaL`3Q9&yg5y0Dyw| zuk5i`;Qw_a4V?FVfA4#F?t3|4=;OQ$$9^jO;nz2RH2K2UMTnrh)4HjTcu5U zloSS#E*1V&qyokK^KI>L{8Y%{3bd>ACyUMgXxwEPerSi95bDBz%i67!nK&(}Tkzbk z-|#sKH`zs92w<-woruqKxjJ4$)xWHu>R%jLP`&CYsPwgJ4kosbhurbi7R))COJ6%h8;Xi)Rk7y8) z^}o_hA7sJJAET}_^BKVSQ-?wcxc-Ksi`H>BDPMoiqQaEPwu^9I3HxIyof|#nC#tn3 z;~4p`%!)(39$lGcL7VTn|Y8RERAsyc&)c*Q$@A zW^p3W>StqQ%_B3UC~s&Hk;aJbFG*XI05M>`>>MwiRz(n;^c72vi2>%~QkF4P_BK)C zW{xDd1q@x z7awL3de~9aB=7|vEC@En$i~r;YSh-6o#w+}XHno|#bnEo*6Ksp7~MKGIVz}6m-+gK zW#J~*B%ZK~dgTP2bY{U}m%7VP`df}ST4ajD->hhY9hoq{)gOz6ESFAl40C<_nTjI? zbns1Flv>x1m9s*xlmL=BbMeJp_J!n6T55|IUJKG3PDnrLGFoLSj*02raq_owOz5SIe-wsW} z0g9GDMmgoBYaQ<}!0-iO4@EQXvldYcwEwF{4B5XE~uXWt!feM6YT zIcxChnLFB=dPZQ=a;FKh>EZ5V{x`417w#s!xP`bg?~JmIVABi0JowppD&=Qkrt5*` zemaY^YBH^y&1KB7&LuTGpq&6tIgj!q>4CqS}-1Ew*&cx%#eZL!VN>38R{ zATq1i&@g~yQgXWD?^79kSUE3!SyJ^qt9FUj!((!obcI-J&1)vR zj+y~qN=ta;k4y?N#03-h)`WRk;e-I|=?QJIt{n*qtz))4g9V|Q zF)pArNtJ+jm%xePlG|=w)Roe8v^3A-bj_fGlt}hJ3l~*BBA2~bE~R&{AscnJV_KR%KdOMmdW>iVLd24WxjsZz}i!>W5y`+`DY}A>OLsqE1zwpn2`b^il>$( z#aW~&I&BgOcQUA$3KyC;tC9qYYMmGA5($ypNYu&3^=qqLB`FXTi>Qwk|4`9p8dOeh zPkKH%y`xmkHBu(1!SbEIQ(cGjk_fdi=Q4x3p13~YND2waVhtTG@x~^i=DAM+9}Svi zxq9ETk7j%nI$~Xh%ntdSbY}nb!5FWTBtOn#`vOcHNuqgSv+LcSxdr9JcGlVl4y2^z zu=^;Dz8>yBBcmHrW>@7=R}Y4r!=XgFT`%Tml{Fzsh?lnIS}H0spSe{B2ZKJk`cS_q zBQLI(bRQAWEw!6#mAP_~jbEzmd5%5bO%RuvWJ{N6I=r*~PN= znJ__&=j{kDBoX$ zA_H@Fd@P6Z2X&>U_^bB^{r!esj*VwR<_extg(@-Gie8)5^8Lg2+oxg$y zV>Cy@K(Vr3@prraxr8+jI^5{UUX?vgH!ySWlckN}7$)Qr3kQdYbF=3e-j0$oHq% z)@j@Y0@+r=W^y3{h-c?lVlm~1hllfc(?Y_`R|ybXm*zt70@ZY-!mZuiT{7J_eB$Eb zl9FoJMmVq3-qmnQ7jBK@%4go+0ssBE`S1d@ObL%;3nh@y`{{D;D<^{~7oWH9OQS@>D1ydAH01Ng0TLTJ5hmfN#+J&H1A3I_(0sY)N z_oDQ=*awGl8P=-rwY3F+x(++ky1}wFg|Z+XMt)TV;@mY^EH-G#d5Phpms~PM`9oo3 z94@^8UP zL3J2$2yGvZ=>B3AQ?L$jX>s-87bTvGDZ^}bm69g{T?E2W7X_6XG+`|+7T@5lOeN- z$78+jPqP0Ljxf08IF8LKXB8`RdlvtrCihx_W1;_iC*S;;9$qP|alYq|kj@X;jwc$I1~#WA^7S?9io^Iehejg%`-?s6qM~)?yxL~hqi&L$XXPD4 z)IQA)*gSbU2R5>|#Vf1J-2wbnPr(Mwo@JW(dsbX$Nz8ejo)KxV&Gd$eba}GU zI`_UFk8NbivHOh0l!(Kfi9WQBWGk^GIcV8(G<3QEA2j})I6q@;j=*7qCPpt*BMY&r z!6U`=llUz!kYy~zV`|Ki@&Rkt+UV(vRnh>%mHj~FjgSM&K zMO&ptjf0Z+-q*U8x@E>7eWl^nR3Qf)Y<-g8vOA~9I)fE5LvVTih%|kH*p3LyHCXya z$6oh7tf^#q&kUa_9{)u|`QSry*~!q!t#wM_Mw~}M zg-XKe!(4hX6C2qj^HNkJBfr^ufJ}>dyr$b!OqkqmW~7wUMcwS*=U~3SxjoErgeVIz zdtNIy=#CA>^JG?kOry6;Kvj~oEfj#m{-c)UWZbb-9NcUCCl+>2%wPi2Eir(i1QRzW zr~38zPY213G-vI4B@)zL(_-Qau$;Hhub3Mu#1nG0QPQ6wwlTKvPl>cmR(KRVm|bMX z?Bnjk$lm-h-)_iI1PzlXem}lqvpxSiPLCXpEc{l{82>CKoOsAV6;9GP0IrQhFlcpy0y%*yI*Nlj~hd(!FwnM|FaM z=i^{2)}~4XN$R;6)|4vrJy=AnHw9<^M;l|rEw z5vMPNo7tL?_rCpUkt7IC;OgfNaFO8(WSHgMZWql%d|mt6t!8SfZdv8J6)o7~`72n= z^pT*UviubtD4}3$xA$(S!WBJ6F9D&nj`CSAU0T+ zPly|Qb~SMF6B+m({Tyx^TBJX%aeferVB#4!*93vI+&n|6CbZ{-RA2bR5})V8A3c65 z?0)#Gt*tHl_2(?O`WV#+L|?`LWFw2aAQV~p?p%S(`6}_)$7n{}a*56?vCp$5(|bch zAYtGOB#}#)K}qjr|KxEXIh-?ht^Sf&Vo?n6C&7l;9d!3_( zzH7B|U=KkL)s{O6=Brw;;Pyrs zvb}Rn_!Exy8+ny4KDUy6f+eD=k*Va0EQvfINOI24Wrmo|o}Eec^vWXb(#1P7<`vhU zvJJub*(6hGyt59r9wwZi@Rp#n&4yp1PHeiw48$#JQ@_C`b!#I6P9@#e%&G~3qpPGiBjTj`kN-zxhjz}d^3B1GD$WZ8O2VLj1e-cT>8ikvP-!e59+N8Hn@PX>i zZ>1jR$&uresA~=LqP7RCrq=)}E&3PP zWM#c(Mf}?hez3=@gkBQOd!9sFaFm;peW0V%PY{11y+8%A1vS#YOkQ9sE06(`j|)$ za*HYH4gEeqMdc>Y_mDt4hvV+&qQ}s0iL>$h7PCId8~J;^1a0&`jO@>7|9F&bV6{?# z+3FPha#zT>*>!+UM8fIkl3{`IM81)xlY7Zou-(82*p3JXuNmo{hV#_r&Gp z`qticn=Ib;*4RGQ^6XzneVEqD&04Z9jB+KH#cHTE^H`%hayZUF5xJW1qZ6j zu{DCngw)b+r^%yZ1NLE(QZo+soA^q;IaLTqV@?Fje!AQg<#v*fem3C&V9)xGd%<)m zc*A58g~z0IDxqFYLJl8gE!8qT1s_7IUE=crhzUK49*Ha5l$+jEwV`g5nGc#uc3*JDxx}OJ@yYr2@ zOehqVuEE8{6{Pu*B$Qq9@pb})*m{SWPl(8Pb#3$l`P1zkKt~-GaKhYu^}fi+?2_;gbDlI4=B2trppj2t0L#TlyXU6T`x}W#?&iT%Doj?2t$y{U3HRc%i zxW~QbLgjD2@DexN`usxJqn?kA^HI=Hthg{_d>kwYX8%^`jE;`1c z4V?uhy8mRcei3ne(Y&hXiYLL+%gT;!jv>s}WYEZSdEVJ$VSS`-wb$AJGY0S2=rT95 z;HhQd__#8-98%Yu=%6-nQ}MAAjtO7RUu}q657{(-8967TG?6}lA1u@SZ-9+clku?Z zc|Q|=M)C6gyoi= z5QHHl-Kv+;DI2^(*;AQ(jp#Nm2Tnh|9X-@|d|S z;*mdO5SY3(m99rCn42MBM0EC(y-1VoqWq3o-YaK}42Fr%KUwN)_ODXRi$CAJ9dES> z_PZ*W<^e|!p|Z4ra}w-MkKQ|pODuZ^B?=Dcj6{|8=g8mThE_xGob<#)U9)ZrZgba# zc^(os>W}FmlvTyPR(ND$AlwdOQ^?t3v?F%y1TlyFr~T128`pJl0{05Rolsyr1x{Rg z|9*FlE0(hUphHF@4kP*6`Ky#MhhUU+LQbrK$b}NclQseET33fi zD}{>LGZNCoVocROigN0NP=5jb(5#S??v3MywHpm@K1Z*mfB(dZ?nwPqTpbz|K94NZ zD1T~~`6)iO$fedp+81ps|8;d2#F;sUA@$Ql7}v1C>z#3n)~RO)`E=?rNdh_O#h4VY zA)f~i9%w{xXL>w0sj_Z~;DHA0fD#r|%(6)GYT{+vjx+@wUiV~eE8Dk5^mXeVl6*67 zKWz5hwQSj=_hoUIR}H(Z5Jq|Fgrh)g`Yqr%QZZ{8~m+wtR^a+6U0{0=e~O7b(tffH`5eP)!)7_ zRYzdR6R|r+|7CZb{rAw?%<%5nZE$~|Tyij5@fmzS6~LH*&bS5gQ}^?vv4)Ft^vDP@ zSsnEJ_KhB6b4&iVnBh?d$X+%&?eH^;vKgqu2;bGpRR~*>GjiPZ7cIcwpTqo<=04@+ zlc(E8t(*CfKAMV8@I(4Dh47!oT!r0#hND}d3^_7vhafv1x0H7ec}Bw}WTLH(fq))l zh!fO^kl$to5aT0YH$u)D!Pmq!F_qrfKhhri{*nJ#B2)#Y)JTW%08U&{CqGP*Qq4>% z(2E|jSSZw2rnq^pOY4`#8sYNu^TmW>y8vMn1QuNrhVYp<3Rf)e{tUkyt#AiBI<3Rbyqzfgl<$V<{};B%K?AUWq;B_hHD&jG zEDl)1$C7m?Qq|drP>w2RD3wskzRFSlH0MltHgKO{KU`vBqK-seEH!5p4NIOLE;O$) zYz63zV2Y@FFr{mMq}dcM;pi1nsoLvObyB;i=7x1n`-xj8=2S)6{5+d(UbLO7YVj$z zQ0@4B*Co!rb|WXm@YAKdJ9e}pN7}+7HA4NlXU-}UH}R}--SUT%Es=b=T0nRG_oUUg z7CFbi-OKgHR4j$+vJl)UDDj#T%>Liq64da9Gt2tOo zLp^fa?io9;yk?D|=xH7WpOtY?2HFknzQA!6c2WQVBQRFqsfS0wSCW}o2&*T;Iy5Vt zzj`h=b9Huf%=mMNT;6wv&&cJ0$#rl3TV)2;x_HA=tDk4D%!t|@SvxBJ%=d|zXqIz= zfcBX-6$kPvP7fF7zcrCyZ>?R^b68ln>zTrXNmiHzgZggZNL|{Q@Qe7WFA1m&)6Dw9 zjlh-zytD15@PU}~fc}{usF0O_dXsruBY5Q84LEZ7l)t3->&s{u?^$WA2yf(;&El2p z>2a}?sf-(fX}>zW@SMwSMf|O~z<{SnmRhN#qzOl0j~=xIyKUf4;L|Tx=laVe z{dUn0kYZC33)XGchjLg_11*~c{dD!k2Kr|FcUOOwaj16eDo?~@! zvOU>YxmR`cl3=sy>{C-0<^v**LKm#(;`*hhYze@N%cG4HR-dqHoy|H53NctNMoS)x+mQF9H z12j-@GbhaXYh`}SvA}>g=W^bsCZGEo3>4;mD(RUQyU|i4KlVw2)86?Uca2dR(^PtH z;+;t(F6TM8{#Dq!W5C0na6^o<-mIH9r*pIEBVrMo*Igr$IzE5C>E5lDfCzZov0cmG zop|Nu-95|6MY_oG!xfg90*>bth`YBri$snnTw#2qb-nk<=rdCn+lwd7htw{)nL6UW z6^gc2T7=t0pJT&wKHCLCRz{q1?xndTE@>w@IYi%SgtO^y&E;8ZC!%YS&f2h(Ob*pXT>>{w zWTUO}Gl0wJ!!PW+3Ud_HkO)gLTSIQh;)Kex zb1Jv=E`XCi8-LB!HzW8I_>NH_+50n_*HM%Yl5=fvW2-%rp2hx|0o&P}IT#E@oih(k zZsW##4dXIN7k5K)G&^`{yQs}rBsl?{^3(Pa@nwCSXr9MuwE`1ldiNl15IL-%fz+H_ zdOiNNC@`rfCX`Wwb}-4!?6eN3m#rD_7!>bd!K!aUS%)+AI)KZ$G^|CTGRN|Bnuv%f%$=)1Z4c24S1zS6c4JxXC2 z2bdyaLX)O|eUIyYtaC+oa+0NA+bvmlwD8?DP9UT~Ay#D2S7DDQ^mw3@uM)I(w2Hat zc~sfPaS19v##6|Z4K$5tO&g`XnM0Meq_xx+a3n9*Mmw-8 zdZoiO4)W*d=A>0`HGcJW&IYLJ>_JFp#XlaRqDm-V+LaZP=SoJB8|+gzM7||cy~zGR{L}Ci+~W zib-zy!DU@));iBq>R7le-wem^*a2fI=Hz9aw8p-auJ1nYF;mi`wjVCWsoQ#*OUi|) zYQ&>A=pV6m&ImrN?%Dn}P;+)g+>!RB>F^?_1|R!>Ox6gw{Qj`S8LW5a=^3$8cDWdm zBFMcPv~HRflZ4OGS82qK1T`U@I-lTkYbHwj=%At-n;7DlQNL5h(;JT)7$u(dj!n1y z?j%yGMlcpEXUXZA+5OlR{T)i*PMwIeR)U55LSgzg+}sVgXx$Wwl1}vAgbv?kVPVhD zmwA+c$m`kd=^DRiQq~UNr#=W#662;Q*frUIvi}v&^f9ctpSgMyRFNJ5GyNkwbwqa0 zA}DQ;_6($jWK(2RX>0~c8mU$rT2Lx<@P41E!!47o11$50An<-SKb#*5YnSjW8~bk$ zx&curIjiV2Fm%soN-X1Mx31|A4@#$EHqy7TJGjT4gBnDMS2YVMsP$otTO9iPJJ;b? z+5#1P7nuq4fL*s0=EbSMz(XaFsB2Kp@CS9V*b8sW&@$!AY zg*#(-MP{v!V-9<=*+&B4sc-?(Ivqo+EjX{6t7$0e_9BG~(19%n6;w6!r}_T_TPgMzgjC7>wKht#n6&jmN;lNy8|)*8_V2ENBsO>3Akf)M;@f}JU%`rn(;hEQI_o-FEC zZz5754Wbd>e~wf*+lUTNDc)%w;?%JIw|ToENK)+PXaaj7X4Tv&B_%z(bpaNaF^1Ur z8j1RsThY_xX^C@B_=M_4JH{hpJfD*D@zWZ*j1WQ&!z$Zv(IzmdV?j=9tZLo7nCQb9BAGh7ruY9g z#hWlkT1mdZTDIgJynAB^TU&wz)VDk&J=AY1bzV&PjEPHMVzrh`?g~raJT8%St0Lp> zul%ZV4`K|}F#8?~JCe_LO*|V7h);?~pGEFvi`Sr0?d}p@uVuGi8$&GFBj52WdH(<^ zGt@iqHsWQnV6Lp|M^l_<4aM@qP@SLg?Y4MvqneTuE8L-=OEPR)@*wvANAd8uNkrh5$rqd3HA5^($WsXlK;-_x`ItrGY_PP~K0u{# zJ%}Sp@?N;*^~%!YGnD-y=t3VGQ6^U}LV2aZ+uzLJr)x<3ah8?Ms3mBx}*cQx0( z**0NW9_Cu}swO(x=stY=cQ4xhw@coG6mBHIWDGk03o*%+FL^WT)rT*trorJEL8XD` z@3QS?SN(Q{=fbVM;uGl!8Z6noS@Gd^U%P+vxIKlOvc?+{$!=LSfNahYCzjr6>n*at zkX9b&E=Ge6l?qqfRc)h)kqNGX@~ev@s=cT8f<_agV0=EK6V8b-RM!SQ*=m2P1CMHmy;!r>pn zof=XyF3gCU*@@U6ca|IY&2>f`v>$1NcHlpGd11BEXx|fRJBL6gxWE|Gp|J5SIC!u2 zaKQFFXoE(Gn%dt6eb9o_@7Lq5F_k`g=kXpL9P&2yvi|kp!)#7DnzKBqq}Bs>%;IW% z7lva$Fvhn(7h|C#dG1K)zXnl2f6Y7}8kg<({oWsR;le195~J zXiI_;YqqxYBu8qP;NIqjml`4(H+5h7GVd_mfmH4~BsQUFu_#vc)y?#n-yhN^E{s;Y zEqte@7H*vSy&L)aG(n6KO7k}G|Kd)FPl7rXJPBws)P@ZU$t>2ACMPE&xMfP;ywPOo ze+_6iK4`#LQy4h5F;x*s{tRfh&a~#N$u|D8SAWHrAY+^bX{@kaLP4Jfc5A;YgKj=C z5P*1I`8OpcS9Olz%bD}+xqe&d5(nSK$l+5J$>dw9*yayg;}&C8Lura50jXzl&~$OO z#V@>m@_hlId^z~`BW?630M5L^E<#qIq;aj((4ik0&(o9?tS6);9yylaEgkoHdPDm!3(0N#y>MN$uWme zx@4DQyOMKfc2e(kfG$ESjl6A%^8qYV%HSX%t-kNVmy3c%2&Sc3_`0I6c{}!ShYvt| zGh;8j-b&p2(Z`a#aS-5b_6)Q!Q5#lfXexK(T?jqW|N6Yu6sL3kZIJdk+W4Sp6yAcY z;YIXEdDCoBu)3W_)M}(h8jxGFWq6cwYs1#|#GNy*WOX>8elXA8c)Gb59&^gkV4_@_ z-f&v~UiIb5jQJY-xfxf2#9Qgqq@-#?<^2|WfT}3<9Md}5O8#MzNsbuAIV8C%9O1vc zRYv9-26WtiQ6YivgX)h-A6LMdnY0h_2jJxX5+1E&YizGr>>M{777JQDdE#)nZagEX z>wr$3txMFZTkW`8frIeo%KJ+WzJNJGcnx~U;*RWS+*sAi;tUtSyMO*Q^&f@$TKdS- zwf{i{0pY8==tuhn1lH@ImZqimAcaN=+!)`Kn8*`(xMS2nmmpvvS0Y)h6FL;*R;V+fZu zs?>)SM^8Vq0Re*x;lDgL_o`zm%PU%!^d`y8$;T>6d}?15u3Kf+22^D9yCbFg!a>`A z?&+9dZfIm!WXdFlj(LG-#&g~*HGxka8EFIR?CQKdhVc1b95KDu3}$j}KPKTOOy=9M zXAEY-ZNOLPeo2RI`Rdmz)cnU+!?>C?bO8_1S7b4jj#8vxN-?Iz=yO8T!|ln^n4ni8 zs?+FL_?h@L7q{2ryS4hShA=W-xJ`GNzg!^1?mEmh(RU3L>0Y1fw21x?iwXzA+o?2= zPOlQbf(}Q@gARiUQJB-$N?4rgm-?76%WEt*3|$Nh12;5dwB#I3nAO<}Uw{)8A1%|X zEjA3X-CPUC?(DDWuX#oTW_$PU`ReJcHVN#_DdbSp^fm59#iBT<1vo5ow9V**n9BSr_O0Q+q@p$b|7)Qb%%fvK-LDjg1M2(--Vt z!~_vE5K=F7un>1YIu00~p+`pfG)Zsvq>aW?T zk{rmbHAl5zi0fC_=%n~>KIH?Uw{Kpe%eHla=CbkkyJHDkOgoBoBQMR}r!(LjAB(_3 z|0rwQG5O?=BKD$qPRZXe&XY-k5po>#42u6IKVWU??Tgz}ZHlYomze-bt{MnDk>pUI z=tj5aX9NvFPkiv3qAi6eApDkOKvXjTluLJQQbA-&z}!;}odO~rkB{S^Kd0fV3<9a0 zShsAUXWd^Xb#!!C-fupF!{JCIQfwDM$Uy*wb(PnS zMku^Q%b`{re_r9@9}r{k8{%{#cvPh1R^!S(Kv<96j3AGY%!KvJzIoJEE>VK#&0F|?5QiTe<^X{89g__+AuEu zDfrc3io{P-nayY(1xm7V2w@0isB`GE!GA}RwK5cdBvWJGQ1k3-{}~Lm!3Cu}p5=Qd zY|}7JpLbv$k&(Wghe(g50j&TeM+ug`A`~4WELo}>YYxcX7$T7f2t{9@UFs3tCvx)? zs()Tk>*c#S;T#8-s(8=jRsvr3l2CuWZ{(n-uGl0? za!WF}f9~M^?Gdk%C7imf7ap17@{MX%|F_Cf&j0$($g{D3KxKT8>=+9{8?ArS>Mb|1 z+;Q3|-z-6GJKW4Iy*81Az$cu2@cdcYrK;^p*A1~7i}d6VuCvO7`FWkDtN2wSBM4aO z+aGS%Cs_)1A8!TJ^7;DBvHt!Wshw({j`Yb08!1-GU-%gRfKde=|G0wEa3*}l8a7Dn_=MXEAPzNEo#X65lIUJ6|*~} z&RmqS=h_S*HfIl|#)ot_E(#LN{QQMOQb+-h}4 zEg`)2GIM$%2%TM}M;!iCN@(5=zroSrJ>fao`=!+Cx=3c*^}`bFg9R~8=3UuIR4&>C zYANWK3+qY;zjiX##_WVE<@MZaXi(bl= z`!o1_91xtzJeUL=ykLFaeVIKlI);-JAEpsye4m31`{T|k<>zn4;Rr0|SkyVpFMZhG z;q|nR3U0-E))Q<%O-8V1{{DJ8ZT+?hEP+)Yho&RGr1v63e|?9&{EzY3 zI|0s!tuH(pCPV&9U1Gu@<{bz12Z(tQSjv$)^}m+B_o3mZOk)I> zD=w$gctEz4)W;1RGlNjZyetKQGGXHwh`f(~#5MoPL|ZTju)6m{7tjGiy&vP3aXonkC}OoS$G}TVT+}NIDnBM^za325%GbYe{&fc5|jej{0 zRZw@R9t~76_*H~2-TGZI6s>*SMYXO@lm9y{d1R6&`{z_@zyA_z~GVALIXS zS-dMCvIkK2(bi@=%$|f+c`2i2=))WpaTI0Ls@X7EIb+Fc_O#5S!a!{JK3>#h& z6RX63XStVnJyWeGLkORt1Ku)0Z=jsKJ>o!KmP14o{2wdhBZca|x3v!w`sn86cq zxt%F857y`UtGOWg=%}t`wSP)Isip>k`(&7P;BS(S@*n_>p8w_^$KE8>FRg@4Z=)ZB zS8+_z|6>aOqzrp^_D6olh=}Xan@yh$PTT-z=l$qLUAzb44%vNMhY4W7U9sx%q3DSR zoeCPo(cl3D_&QLuNLqk6243hR)pQ|`IN*2GuK#_YHFG4FrFWnu5GZiVc+Pk{YA%?)GIJsI_&lvTK%!WsranQ0YHf5}W7eh4Ku zeO`gmmIa~Y;12eKyhFCwOF9O~`TBIC|Nf%-(H8u;EtHniu@N}UFo~<5&*daY^9^N_ z)bw|3Xp6M57TIAog&@;3cGQ9}=a&e+_*7x&POE%BYUy%h_iDD5COrDgX|*>%RRA6< zNtgGDK|AvCq8KwGftNfoIgskWor4BAyMK+;XR@I(q+I>N=lTXMded+!-V<8`UaD3I@+4dqvFAn%<->Mb)<0H8NuhzO>PMae zkiw3xkOGnkhd<6LDcoQAybZ0P4J0F8LY_+PqWg9bkD~u(RFHtt{x*QE5tK0DUOfd2 zi7_~|YH=$;q=daFKpU9ljlB{r&JHamQTXK^2Fq7&2pyQ~#4dTsBASN%zaKBnoy{T* zb^*Kkfrtohl}?l|B&kIS^~1%I0wnj_i}nP8V?6yyFsExj!24eoeVHeEAiNXzto1Xx zazg`BB-g&Ywk{7BIjcNS=2q{$NQGA04_9GPSErb?{}^I&2}rsv_vTdn{j4a0x#j8a zi=E=r{-}=!t@t^id)KL*^h@qEC!`5(4`O9s{bkM;;em!o32ifY%Dw&x)M9&%4@oBG zrf~^q|GcC6NLywpv=t{E1`F# zSWRKK@ilt*sGp2@BHO1WP34We0ogsam}N=fK-F+kQ`F z(?iCD+n^R3F&!Jv>DF{&S1$!`G<+75O`jxET3S~m>UT;zytG_LDT3WmoML_D**o$U!CkIQ8E-w@S7f>QO**3B&eQc>N5l1V zPh%B#dOszzQzt$&%0lfPEiIr{AqQL=D^1-M+X19J)n<-9>QV2y=TQ9kf<{xA6LrWD z*wI1)c94b_mQ{UOiscbI9b%kA>*>6>ElC@dcm#6OI5i>J;E{lltoF1BOT+X}PQ@Xk z)@No8^rnz@^Za#o7dOq+<;g)^gI^br##2nNKZZyWShdl?rMPTxiOiPaQ*GjrwM8VP z;FFTmSpQMZ;0z9)ybI`oFRw$2m9YgcxbxLggrff2y65T}nTeo#O76r0M* ziCy$pX0ctA7gO_VG~mE<9o3z!<$rQ-CbXq>F0dtHb|<6t;7DjM51N^{$e60Pl*1Ge z-Ty-&?7He1wl*w1doW!wTgUJfrPt9$rlz>%FmZ!bzGPD>Sffm53g^E9`tSbatM6F% zSd}lKCGh1a)=ur^xX_?#dHIu{Z2lM}Z;KWVR=nV8NUo|kJfmFUX-o6XOHGrwuWhkg zab0cMwhPn3LiN?`ZeZP+b{<{oaklk0=y>axnT!h%>=(pWikKm46`grkv--2E*Z_gJ0DY=K`4)7?t&hD6Bnu3}X zZCR(eiVuS$2?f}6?mrOoQgh1MA5~nkwb>^iU=*|O?kUP06{R7C)QyeyD%5Ewmw`Qi zYzmPE6f4Er+aw%cD8)Ov+G#(pxRdajttkU+^Thc9X*Br2pQPXuZqB8E7{d=srxee7 zr|Q}aR;_SKr|-Kva#*5XO*n?O(LUp6`4;Hb5y&gG5M|a*$2|{uf37h>`?Z74IFANz zX7$Dud2mKr_pWOS26qe=3#FErISeK^Fkam3e17Irm-9AEw2Iv8{Z9NDcqc9IlMF7? z_c=qC_|PhNYBw^|Ol0AxT%`&ey4n<@kvAmiJkpxFqROP7PX#)m=~}%GMhQyBC!r2h zR(N@+1If4`>h4`D>Se@M&C-92leKtdfVu6Pw^Q0Q13E3wFxJPqLcQST?KM^78J-qE zioJ{XVPE-|au;gXNxTRv~U4Nc?L=1&Bmxx5UjrMdK#V~U?g6J(|PrUy!5vlGY?Wcz-qyFIAaeG_C`06#MCom4@Gh7C$bt<%O4wZk%X)apG!)Yn#he z0=4E7lVnZKm=N`IUo+puezvm|$khpgYpt{tBW=cUEb`B}edS9ZwoB^N8Kw`ol9gfG zEhUAVGkznR>Pl)~mi(SiXt7yoJK@D!&Mcam);2keLw!uW%cN;_A66u#7~y>B#?nI% zcscnh!7MFC>9chGn`Pb?T%GO6_r&;+%eV9Eub$U|xu)zg@^VK}Uu_VhJBP*U6GA18 zr?&N)b*`a$RrzwLtCO21#pWlH16|W(F$>fCyb8abT;bgi3RwbM#plOd1FiOJ7BZ{6 zG0YqMS|ILwQu|Pk?540|;|4r52#g*HLlSpYu^p-M!7b*lhs`8hpC8(kGLpaR0n{*t zi;(!-*5i3DSd#NuN}-AnDrWmgq{=2(NO`*ZnFv=1u#Rfq8Wu4Ax;I=O=}!ug3!N>y z7)~E}X{o(yz_qT@%>%cA!60t0Jz3FkeK3$;Z!1XCVbbXtXEhqI$39EY)j)QBuo!Ny zSyl`xKE&|pJAF+&48`8xE8;9?GkZJPB|hvQ*Mp_#Nf;)%TfOcn%SH;I7+finj_v{o zAI&__$QWb$7>QiAdvOw;6|b{HY%lH#`$kf^pKF0kir0Nf{t#>Dy)R(yAbvA;Q((8p z(8HBk^qkv0dJW9akRgvw&3ACzReI*s7H!-nNO)>$^N>r=Ghv1o_kFAc{(vc5cg1KBAy&-S!M zk6L$L`|>zg!Sm!;<7=A+K0{f{rzW zTQTgK76WaOsMvke^mkq8?E8OoRJJ{im0-$#_i^;_^So{~Mr9`cZZ!^z)7@&1uWDFz z6P|N5oR;{4?3n8cF8GIYkYxHr{%SJ4! z)G>&B=7461@O!(y#>2d!p%?#SuugsPKV+VAn zmm1!w{&_&q_+Z1*cbG|@JtHe&cQl)Nk=5=vlVHYB4T0>#dF7(q=j2(BCtb}k9%X3# zaO%fLPP|7LGkXf6^n-)6G0F@fe6FR+Fh|uw=Ae#~r9zCSp?{9mM_1KrSftWq5r8+I2MpWXY| zST^2rf%Oo_Uvt(TYd6iaM`RKLvvrt)4!(~P2k)g(Z2^nk$eDRiIqPYND}zUP=56?N zmQsdb)U-g@`53@#tM5UHs{D9M-NJu;iPQh>hXn7bR2rWlL-m8S%^CvmCk8DwUDYCG Ht4IF}4xEy) literal 0 HcmV?d00001 diff --git a/IfSharp-MatrixVector.png b/IfSharp-MatrixVector.png new file mode 100644 index 0000000000000000000000000000000000000000..3d69ed3cb96095dda11d52b4ed4841a3ac0c8170 GIT binary patch literal 47785 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 literal 0 HcmV?d00001 diff --git a/IntegralTransforms.html b/IntegralTransforms.html index ab38de59..d855c7c0 100644 --- a/IntegralTransforms.html +++ b/IntegralTransforms.html @@ -1,63 +1,138 @@ - - - Fourier and related linear integral transforms + +<head> + <meta charset="utf-8"> + <title>Fourier and related linear integral transforms - - - - - - - - - - - - - - - - - - -
      -
      - -

      Math.NET Numerics

      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      +
      +

      Fourier and related linear integral transforms

      Math.NET Numerics currently supports two linear integral transforms: The discrete Fourier transform and the discrete Hartley transform. Both are strongly localized in the frequency spectrum, but while the Fourier transform operates on complex values, the Hartley transform @@ -75,15 +150,7 @@ We provide implementations of the following algorithms:

      Furthermore, the Transform class provides a shortcut for the Bluestein FFT using static methods which are even easier to use: FourierForward, FourierInverse.

      Code Sample using the Transform class:

      - -
      1: 
      -2: 
      -3: 
      -4: 
      -5: 
      -6: 
      -7: 
      -
      // create a complex sample vector of length 96
      +
      // create a complex sample vector of length 96
       Complex[] samples = SignalGenerator.EquidistantInterval(
            t => new Complex(1.0 / (t * t + 1.0), t / (t * t + 1.0)),
            -16, 16, 96);
      @@ -114,88 +181,16 @@ Transform.FourierForward(samples);
       

      Hartley Space: Discrete Hartley Transform

      ...

      - - -
      - -
      - + - + + + + + + + + + + diff --git a/Integration.html b/Integration.html index 6c95eaff..b04a2037 100644 --- a/Integration.html +++ b/Integration.html @@ -1,78 +1,141 @@ - - - Numerical Integration + +<head> + <meta charset="utf-8"> + <title>Numerical Integration - - - - - - - - - - - - - - - - - - -
      -
      - -

      Math.NET Numerics

      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      +
      +

      Numerical Integration

      The following double precision numerical integration or quadrature rules are supported in Math.NET Numerics under the MathNet.Numerics.Integration namespace. Unless stated otherwise, the examples below evaluate the integral \(\int_0^{10} x^2 \, dx = \frac{1000}{3} \approx 333.\overline{3}\).

      Simpson's Rule

      - -
       1: 
      - 2: 
      - 3: 
      - 4: 
      - 5: 
      - 6: 
      - 7: 
      - 8: 
      - 9: 
      -10: 
      -11: 
      -
      // Composite approximation with 4 partitions
      +
      // Composite approximation with 4 partitions
       double composite = SimpsonRule.IntegrateComposite(x => x * x, 0.0, 10.0, 4);
       
       // Approximate value using IntegrateComposite with 4 partitions is: 333.33333333333337
      @@ -85,25 +148,7 @@ Console.WriteLine("Approximate value using IntegrateComposite wi
       Console.WriteLine("Approximate value using IntegrateThreePoint is: " + threePoint);
       

      Newton Cotes Trapezium Rule

      - -
       1: 
      - 2: 
      - 3: 
      - 4: 
      - 5: 
      - 6: 
      - 7: 
      - 8: 
      - 9: 
      -10: 
      -11: 
      -12: 
      -13: 
      -14: 
      -15: 
      -16: 
      -17: 
      -
      // Adaptive approximation with a relative error of 1e-5
      +
      // Adaptive approximation with a relative error of 1e-5
       double adaptive = NewtonCotesTrapeziumRule.IntegrateAdaptive(x => x * x, 0.0, 10.0, 1e-5);
       
       // Approximate value of the integral using IntegrateAdaptive with a relative error of 1e-5 is: 333.333969116211
      @@ -123,13 +168,7 @@ Console.WriteLine("Approximate value using IntegrateTwoPoint is:
       

      Double-Exponential Transformation

      The Double-Exponential Transformation is suited for integration of smooth functions with no discontinuities, derivative discontinuities, and poles inside the interval.

      - -
      1: 
      -2: 
      -3: 
      -4: 
      -5: 
      -
      // Approximate using a relative error of 1e-5.
      +
      // Approximate using a relative error of 1e-5.
       double integrate = DoubleExponentialTransformation.Integrate(x => x * x, 0.0, 10.0, 1e-5);
       
       // Approximate value using a relative error of 1e-5 is: 333.333333333332
      @@ -142,20 +181,7 @@ Console.WriteLine("Approximate value using a relative error of 1
       

      This algorithm calculates the abscissas and weights for a given order and integration interval. For efficiency, pre-computed abscissas and weights for the orders \(N = 2 - 20, \, 32, \, 64, \, 96, 100, \, 128, \, 256, \, 512, \, 1024\) are used. Otherwise, they are calculated on the fly using Newton's method. For more information on the algorithm see [Holoborodko, Pavel] .

      Abscissas and Weights

      We'll first use the abscissas and weights to approximate an integral using a 5-point Gauss-Legendre rule

      - -
       1: 
      - 2: 
      - 3: 
      - 4: 
      - 5: 
      - 6: 
      - 7: 
      - 8: 
      - 9: 
      -10: 
      -11: 
      -12: 
      -
      // Create a 5-point Gauss-Legendre rule over the integration interval [0, 10]
      +
      -
      // Create a 5-point Gauss-Legendre rule over the integration interval [0, 10]
       GaussLegendreRule rule = new GaussLegendreRule(0.0, 10.0, 5);
       
       double sum = 0; // Will hold the approximate value of the integral
      @@ -174,23 +200,7 @@ Console.WriteLine("Approximate value is: " 
       1: 
      - 2: 
      - 3: 
      - 4: 
      - 5: 
      - 6: 
      - 7: 
      - 8: 
      - 9: 
      -10: 
      -11: 
      -12: 
      -13: 
      -14: 
      -15: 
      -
      // Create a 5-point Gauss-Legendre rule over the integration interval [0, 10]
      +
      // Create a 5-point Gauss-Legendre rule over the integration interval [0, 10]
       GaussLegendreRule rule = new GaussLegendreRule(0.0, 10.0, 5);
       
       double[] x = rule.Abscissas; // Creates a clone and returns array of abscissas
      @@ -207,19 +217,7 @@ GaussLegendreRule rule = new Gauss
       Console.WriteLine("Approximate value is: " + sum);;
       

      In addition to obtaining the abscissas and weights, the order and integration interval can be obtained

      - -
       1: 
      - 2: 
      - 3: 
      - 4: 
      - 5: 
      - 6: 
      - 7: 
      - 8: 
      - 9: 
      -10: 
      -11: 
      -
      // Create a 5-point Gauss-Legendre rule over the integration interval [0, 10]
      +
      // Create a 5-point Gauss-Legendre rule over the integration interval [0, 10]
       GaussLegendreRule rule = new GaussLegendreRule(0.0, 10.0, 5);
       
       // The order of the rule is: 5
      @@ -233,19 +231,7 @@ Console.WriteLine("The upper integral bound is: " 

      Integrate Method

      For convenience, we provide an overloaded static method double Integrate(...) which preforms 1D and 2D integration of a function. The first parameter to the method is a delegate of type Func<double, double> or Func<double, double, double> for 1D and 2D integration respectively. So for example

      - -
       1: 
      - 2: 
      - 3: 
      - 4: 
      - 5: 
      - 6: 
      - 7: 
      - 8: 
      - 9: 
      -10: 
      -11: 
      -
      // 1D integration using a 5-point Gauss-Legendre rule over the integration interval [0, 10]
      +
      // 1D integration using a 5-point Gauss-Legendre rule over the integration interval [0, 10]
       double integrate1D = GaussLegendreRule.Integrate(x => x * x, 0.0, 10.0, 5);
       
       // Approximate value of the 1D integral is: 333.333333333333
      @@ -259,88 +245,16 @@ Console.WriteLine("Approximate value of the 2D integral is: "

      where we used \(\int_0^{10}\int_1^2 x^2 y^2 \,dydx = \frac{7000}{9} \approx 777.\overline{7}\) for the 2D integral example.

      - - -
      - -
      - + - + + + + + + + + + + diff --git a/Interpolation.html b/Interpolation.html index a149ffff..67fb50f9 100644 --- a/Interpolation.html +++ b/Interpolation.html @@ -1,63 +1,138 @@ - - - Interpolation + +<head> + <meta charset="utf-8"> + <title>Interpolation - - - - - - - - - - - - - - - - - - -
      -
      - -

      Math.NET Numerics

      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      +
      +

      Interpolation

      Namespace: MathNet.Numerics.Interpolation

      Interpolation is a two-phased operation in Math.NET Numerics:

        @@ -94,88 +169,16 @@
      1. Generic Cubic Hermite Spline, requires the derivatives
      2. - -
      -
      - -
      -
      +
      - + + + + + + + +
      + + diff --git a/LinearEquations.html b/LinearEquations.html index 8c64a9cd..17996c27 100644 --- a/LinearEquations.html +++ b/LinearEquations.html @@ -1,63 +1,138 @@ - - - Linear Equation Systems - - - - - - - - - - - - - - - - - - -
      -
      - -

      Math.NET Numerics

      + + + Linear Equation Systems + + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      +
      +

      Linear Equation Systems

      A system of linear equations is a collection of linear equations involving the same set of variables:

      \[\begin{alignat}{7} 3x &\; + \;& 2y &\; - \;& z &\; = \;& 1 & \\ @@ -93,15 +168,7 @@ a_{m1} & a_{m2} & \cdots & a_{mn} \;=\; \begin{bmatrix}1\\-2\\0\end{bmatrix}\]

      Which we can solve explicitly with the LU-decomposition, or simply by using the Solve method:

      - -
      1: 
      -2: 
      -3: 
      -4: 
      -5: 
      -6: 
      -7: 
      -
      var A = Matrix<double>.Build.DenseOfArray(new double[,] {
      +
      var A = Matrix<double>.Build.DenseOfArray(new double[,] {
           { 3, 2, -1 },
           { 2, -2, 4 },
           { -1, 0.5, -1 }
      @@ -111,20 +178,12 @@ a_{m1} & a_{m2} & \cdots & a_{mn}
       

      The resulting \(\mathbf{x}\) is \([1,\;-2,\;-2]\), hence the solution \(x=1,\;y=-2,\;z=-2\).

      In F# the syntax is a bit lighter:

      - - - -
      1: 
      -2: 
      -3: 
      -4: 
      -5: 
      -
      let A = matrix [[ 3.0; 2.0; -1.0 ]
      -                [ 2.0; -2.0; 4.0 ]
      -                [ -1.0; 0.5; -1.0 ]]
      -let b = vector [ 1.0; -2.0; 0.0 ]
      -let x = A.Solve(b) // 1;-2;-2
      -
      +
      let A = matrix [[ 3.0; 2.0; -1.0 ]
      +                [ 2.0; -2.0; 4.0 ]
      +                [ -1.0; 0.5; -1.0 ]]
      +let b = vector [ 1.0; -2.0; 0.0 ]
      +let x = A.Solve(b) // 1;-2;-2
      +

      Normalizing Equation Systems

      In practice, a linear equation system to be solved is often not in the standard form required to use the linear algebra approach. For example, let's have a look at the following system:

      @@ -151,111 +210,30 @@ become zero on the right side), by introducing a new column each. First we subtr \;=\; \begin{bmatrix}0\\0\\20\\0\end{bmatrix}\]

      Which is in standard from, so we can solve normally:

      - - - -
      1: 
      -2: 
      -3: 
      -4: 
      -5: 
      -6: 
      -
      let A' = matrix [[ 3.0; 4.0; -1.0; 0.0 ]
      -                 [ 4.0; 5.0; 0.0; -1.0 ]
      -                 [ 5.0; 6.0; 0.0; 0.0; ]
      -                 [ 6.0; 7.0; 0.0; 0.0 ]]
      -let b' = vector [ 0.0; 0.0; 20.0; 0.0 ]
      -let x' = A'.Solve(b') // -140; 120; 60; 40
      -
      - -
      val A : obj

      Full name: LinearEquations.A
      -
      val b : obj

      Full name: LinearEquations.b
      -
      val x : obj

      Full name: LinearEquations.x
      -
      val A' : obj

      Full name: LinearEquations.A'
      -
      val b' : obj

      Full name: LinearEquations.b'
      -
      val x' : obj

      Full name: LinearEquations.x'
      - - -
      - -
      - - + + + + + + + + + + diff --git a/MKL.html b/MKL.html index bb75543f..50d83e43 100644 --- a/MKL.html +++ b/MKL.html @@ -1,63 +1,138 @@ - - - Intel Math Kernel Library (MKL) + +<head> + <meta charset="utf-8"> + <title>Intel Math Kernel Library (MKL) - - - + + + + + + - - - - + - - - - - + + + + + + + + + + + + - - - -
      -
      - -

      Math.NET Numerics

      + + +
      + +
      +
      +

      Intel Math Kernel Library (MKL)

      Math.NET Numerics is designed such that performance-sensitive algorithms can be swapped with alternative implementations by the concept of providers. There is currently only a provider for linear algebra related routines, but there @@ -77,15 +152,11 @@ only a single platform, for example:

      In order to leverage the MKL linear algebra provider, we need to make sure the .NET runtime can find the native libraries (see below) and then enable it by calling:

      - -
      1: 
      -
      Control.UseNativeMKL();
      +
      Control.UseNativeMKL();
       

      Alternatively you can also enable it by setting the environment variable MathNetNumericsLAProvider=MKL.

      You can also explicitly disable the MKL provider by forcing it to use the managed provider by calling:

      - -
      1: 
      -
      Control.UseManaged();
      +
      Control.UseManaged();
       

      You can tell what provider is effectively loaded by calling Control.LinearAlgebraProvider.ToString(), which will return something along the lines of Intel MKL (x86; revision 7).

      @@ -147,12 +218,7 @@ If not, you can get a free trial on intel's web site.
    • Run the .sh script by typing sh mkl_build.sh
    • ... wait for the build
    • - -
      1: 
      -2: 
      -3: 
      -4: 
      -
      lionel:~ Lionel$ cd /Users/Lionel/Public/Git/GitHub/mathnet-numerics/src/NativeProviders/OSX
      +
      lionel:~ Lionel$ cd /Users/Lionel/Public/Git/GitHub/mathnet-numerics/src/NativeProviders/OSX
       lionel:OSX Lionel$ ls
       mkl_build.sh
       lionel:OSX Lionel$ sh mkl_build.sh
      @@ -160,10 +226,7 @@ lionel:OSX Lionel$ sh mkl_build.sh
       

      Check the /x86 and /x64 folders in mathnet-numerics/out/MKL: you should now find the libiomp5.dylib and MathNet.Numerics.MKL.dll libaries. You need to add the path to the generated libraries in your DYLD_LIBRARY_PATH environment variable (which you can move to the folder of you choice before). To do that, open your /Users/Lionel/.bas_profile.sh file with a text editor and add the following statements.

      - -
      1: 
      -2: 
      -
      export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/Users/Lionel/../mathnet-numerics/out/MKL/OSX/x64
      +
      export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/Users/Lionel/../mathnet-numerics/out/MKL/OSX/x64
       export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/Users/Lionel/../mathnet-numerics/out/MKL/OSX/x86
       

      Of course replace Lionel by your account login.

      @@ -171,32 +234,19 @@ export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/Users/Lionel/../mathnet-numerics/ou

      F# Interactive

      In F# Interactive, the easiest way to use native providers is to copy them to a shared directory somewhere and use them directly from there:

      - - - -
      1: 
      -2: 
      -
      Control.NativeProviderPath <- @"C:\MKL"
      -Control.UseNativeMKL()
      -
      +
      Control.NativeProviderPath <- @"C:\MKL"
      +Control.UseNativeMKL()
      +

      If you are using the F# Power Tools in VisualStudio, you can also let it generate "Reference scripts for F# Interactive" right from the context menu. This will generate a script called load-references.fsx in a Scripts folder, which you can extend as follows to load the MKL provider automatically.

      - - - -
      1: 
      -2: 
      -3: 
      -4: 
      -5: 
      -
      open System.IO
      -open MathNet.Numerics
      +
      open System.IO
      +open MathNet.Numerics
       
      -Control.NativeProviderPath <- Path.Combine(__SOURCE_DIRECTORY__,"../")
      -Control.UseNativeMKL()
      -
      +Control.NativeProviderPath <- Path.Combine(__SOURCE_DIRECTORY__,"../") +Control.UseNativeMKL() +

      This script assumes that the MKL binaries have been copied to the project directory, which is also where the NuGet packages place them by default. If you place them somewhere else, adapt the path accordingly.

      @@ -206,66 +256,25 @@ for more alternatives.

      The automatic strategy may still work if assembly shadowing is involved, but it often simpler and more reliable to provide the folder explicitly. This also works well in LINQPad, with and without assembly shadowing:

      - -
      1: 
      -2: 
      -
      Control.NativeProviderPath = @"C:\MKL";
      +
      Control.NativeProviderPath = @"C:\MKL";
       Control.UseNativeMKL();
       

      Example: Intel MKL on Linux with Mono

      We also provide MKL NuGet package for Linux if you do not want to build them yourself. Assuming you have Mono and NuGet installed (here v3.2.8), you can fetch the MKL package of the right architecture (x64 or x86, uname -m if you don't know) as usual:

      - -
      1: 
      -2: 
      -
      mono nuget.exe install MathNet.Numerics -Pre -OutputDirectory packages
      +
      mono nuget.exe install MathNet.Numerics -Pre -OutputDirectory packages
       mono nuget.exe install MathNet.Numerics.MKL.Linux-x64 -Pre -OutputDirectory packages
       

      Native assembly resolving is very different on Linux than on Windows, simply putting the native libraries into the same folder as the executable is not enough. The safe way is to edit /etc/ld.so.conf and use ldconfig to tell where to look for the libraries, but for now we'll just copy them to /usr/lib:

      - -
      1: 
      -2: 
      -
      sudo cp packages/MathNet.Numerics.MKL.Linux-x64.1.3.0/content/libiomp5.so /usr/lib/
      +
      sudo cp packages/MathNet.Numerics.MKL.Linux-x64.1.3.0/content/libiomp5.so /usr/lib/
       sudo cp packages/MathNet.Numerics.MKL.Linux-x64.1.3.0/content/MathNet.Numerics.MKL.dll /usr/lib/
       

      Then we're all set and can just call Control.UseNativeMKL() if we want to use the native provider. Let's create the following C# file Example.cs:

      - -
       1: 
      - 2: 
      - 3: 
      - 4: 
      - 5: 
      - 6: 
      - 7: 
      - 8: 
      - 9: 
      -10: 
      -11: 
      -12: 
      -13: 
      -14: 
      -15: 
      -16: 
      -17: 
      -18: 
      -19: 
      -20: 
      -21: 
      -22: 
      -23: 
      -24: 
      -25: 
      -26: 
      -27: 
      -28: 
      -29: 
      -30: 
      -31: 
      -
      using System;
      +
      using System;
       using System.Diagnostics;
       using MathNet.Numerics;
       using MathNet.Numerics.LinearAlgebra;
      @@ -298,13 +307,7 @@ Let's create the following C# file Example.cs:

      }

      Compile and run:

      - -
      1: 
      -2: 
      -3: 
      -4: 
      -5: 
      -
      # single line:
      +
      # single line:
       mcs -optimize -lib:packages/MathNet.Numerics.3.0.0-alpha8/lib/net40/
                     -r:MathNet.Numerics.dll Example.cs -out:Example
       # launch:
      @@ -320,93 +323,32 @@ Numerics MKL native provider for free for your own use. However, it does not
       redistribute it again yourself to customers of your own product. If you need to redistribute,
       buy a license from Intel. If unsure, contact the Intel sales team to clarify.

      -
      namespace Microsoft.FSharp.Control
      -
      namespace System
      -
      namespace System.IO
      -
      type Path =
        static val DirectorySeparatorChar : char
        static val AltDirectorySeparatorChar : char
        static val VolumeSeparatorChar : char
        static val InvalidPathChars : char[]
        static val PathSeparator : char
        static member ChangeExtension : path:string * extension:string -> string
        static member Combine : [<ParamArray>] paths:string[] -> string + 3 overloads
        static member GetDirectoryName : path:string -> string
        static member GetExtension : path:string -> string
        static member GetFileName : path:string -> string
        ...

      Full name: System.IO.Path
      -
      Path.Combine([<System.ParamArray>] paths: string []) : string
      Path.Combine(path1: string, path2: string) : string
      Path.Combine(path1: string, path2: string, path3: string) : string
      Path.Combine(path1: string, path2: string, path3: string, path4: string) : string
      +
      Namespace Microsoft.FSharp.Control
      +
      Namespace System
      +
      Namespace System.IO
      +
      type Path = + static member ChangeExtension : path: string * extension: string -> string + static member Combine : path1: string * path2: string -> string + 3 Überladungen + static member EndsInDirectorySeparator : path: ReadOnlySpan<char> -> bool + 1 Überladung + static member GetDirectoryName : path: ReadOnlySpan<char> -> ReadOnlySpan<char> + 1 Überladung + static member GetExtension : path: ReadOnlySpan<char> -> ReadOnlySpan<char> + 1 Überladung + static member GetFileName : path: ReadOnlySpan<char> -> ReadOnlySpan<char> + 1 Überladung + static member GetFileNameWithoutExtension : path: ReadOnlySpan<char> -> ReadOnlySpan<char> + 1 Überladung + static member GetFullPath : path: string -> string + 1 Überladung + static member GetInvalidFileNameChars : unit -> char [] + static member GetInvalidPathChars : unit -> char [] + ...
      <summary>Performs operations on <see cref="T:System.String" /> instances that contain file or directory path information. These operations are performed in a cross-platform manner.</summary>
      +
      Path.Combine([<System.ParamArray>] paths: string []) : string
      Path.Combine(path1: string, path2: string) : string
      Path.Combine(path1: string, path2: string, path3: string) : string
      Path.Combine(path1: string, path2: string, path3: string, path4: string) : string
      - -
      - -
      - - + + + + + + + + + + diff --git a/MatlabFiles.html b/MatlabFiles.html index d7d626b1..a76c1e21 100644 --- a/MatlabFiles.html +++ b/MatlabFiles.html @@ -1,89 +1,145 @@ - - - MATLAB Level-5 Mat Files + +<head> + <meta charset="utf-8"> + <title>MATLAB Level-5 Mat Files - - - - - - - - - - - - - - - - - - -
      -
      - -

      Math.NET Numerics

      + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      +
      +

      MATLAB Level-5 Mat Files

      Level-5 MATLAB Mat files are popular as binary file container for storing one or more matrices. Math.NET Numerics provides basic support for such Mat files with the MathNet.Numerics.Data.Matlab package, which is available on NuGet as separate package and not included in the basic distribution.

      Reading matrices from a MATLAB file

      The MatlabReader class provides static functions to list all matrices stored in a MAT file or stream, and to read them individually as Math.NET matrices:

      - -
       1: 
      - 2: 
      - 3: 
      - 4: 
      - 5: 
      - 6: 
      - 7: 
      - 8: 
      - 9: 
      -10: 
      -11: 
      -12: 
      -13: 
      -14: 
      -15: 
      -16: 
      -17: 
      -18: 
      -
      using MathNet.Numerics.LinearAlgebra;
      +
      using MathNet.Numerics.LinearAlgebra;
       using MathNet.Numerics.Data.Matlab;
       
       // read the first matrix as double
      @@ -105,11 +161,7 @@ Dictionary<string,Matrix<doubleAlternatively the reader can list all matrices of a file into named data elements,
       which can then be read into matrices individually. This is useful e.g. if we need to
       read some of the matrices to a different type:

      - -
      1: 
      -2: 
      -3: 
      -
      List<MatlabMatrix> ms = MatlabReader.List("collection.mat");
      +
      List<MatlabMatrix> ms = MatlabReader.List("collection.mat");
       Matrix<double> Ad = MatlabReader.Unpack<double>(ms.Find(m => m.Name == "Ad"));
       Matrix<float> vd = MatlabReader.Unpack<float>(ms.Find(m => m.Name == "vd"));
       
      @@ -117,31 +169,14 @@ Matrix<float> vd = MatlabRea

      The dual to the reader above is the MatlabWriter class that can serialize matrices to a MATLAB file or stream. Like the reader, the writer can use MatlabMatrix data elements to compose packed matrices into a file. Each matrix has a name which must not contain spaces.

      - -
      1: 
      -2: 
      -3: 
      -4: 
      -
      var matrices = new List<MatlabMatrix>();
      +
      var matrices = new List<MatlabMatrix>();
       m.Add(MatlabWriter.Pack(myFirstMatrix, "m1");
       m.Add(MatlabWriter.Pack(mySecondMatrix, "m2");
       MatlabWrier.Store("file.mat", matrices);
       

      But there are also direct routines if only a single matrix or matrices of all the same data type are to be stored in a file:

      - -
       1: 
      - 2: 
      - 3: 
      - 4: 
      - 5: 
      - 6: 
      - 7: 
      - 8: 
      - 9: 
      -10: 
      -11: 
      -
      // write a single matrix "myMatrix" and name it "m1".
      +
      // write a single matrix "myMatrix" and name it "m1".
       MatlabWriter.Write("file.mat", myMatrix, "m1");
       
       // write multiple matrices, from a list of matrices and a list of their names:
      @@ -161,88 +196,16 @@ Among others:

    • NIST MatrixMarket text files
    • - - -
      - -
      - + - + + + + + + + + + + diff --git a/Matrix.html b/Matrix.html index 4f521d30..2b044e0b 100644 --- a/Matrix.html +++ b/Matrix.html @@ -1,63 +1,138 @@ - - - Matrices and Vectors - - - - - - - - - - - - - - - - - - -
      -
      - -

      Math.NET Numerics

      + + + Matrices and Vectors + + + + + + + + + + + + + + + + + + + + + + + + + +
      + +
      +
      +

      Matrices and Vectors

      Math.NET Numerics includes rich types for matrices and vectors. They support both single and double precision, real and complex floating point numbers.

      \[\mathbf{A}= @@ -109,14 +184,7 @@ For example, for double precision numbers there is a DenseMatrix cl namespace. You do not normally need to be aware of that, but as consequence the generic Matrix<T> type is abstract and we need other ways to create a matrix or vector instance.

      The matrix and vector builder provide functions to create instances from a variety of formats or approaches.

      - -
      1: 
      -2: 
      -3: 
      -4: 
      -5: 
      -6: 
      -
      // create a dense matrix with 3 rows and 4 columns
      +
      // create a dense matrix with 3 rows and 4 columns
       // filled with random numbers sampled from the standard distribution
       Matrix<double> m = Matrix<double>.Build.Random(3, 4);
       
      @@ -125,14 +193,7 @@ Vector<double> v = Vector<
       

      Since within an application you often only work with one specific data type, a common trick to keep this a bit shorter is to define shortcuts to the builders:

      - -
      1: 
      -2: 
      -3: 
      -4: 
      -5: 
      -6: 
      -
      var M = Matrix<double>.Build;
      +
      var M = Matrix<double>.Build;
       var V = Vector<double>.Build;
       
       // build the same as above
      @@ -143,25 +204,7 @@ is to define shortcuts to the builders:

      so if we'd like to build a sparse matrix, intellisense will list all available options together once you type M.Sparse.

      There are variants to generate synthetic matrices, for example:

      - -
       1: 
      - 2: 
      - 3: 
      - 4: 
      - 5: 
      - 6: 
      - 7: 
      - 8: 
      - 9: 
      -10: 
      -11: 
      -12: 
      -13: 
      -14: 
      -15: 
      -16: 
      -17: 
      -
      // 3x4 dense matrix filled with zeros
      +
      // 3x4 dense matrix filled with zeros
       M.Dense(3, 4);
       
       // 3x4 dense matrix filled with 1.0.
      @@ -182,46 +225,7 @@ M.Random(3, 4, new
       

      But often we already have data available in some format and need a matrix representing the same data. Whenever a function contains "Of" in its name it does create a copy of the original data.

      - -
       1: 
      - 2: 
      - 3: 
      - 4: 
      - 5: 
      - 6: 
      - 7: 
      - 8: 
      - 9: 
      -10: 
      -11: 
      -12: 
      -13: 
      -14: 
      -15: 
      -16: 
      -17: 
      -18: 
      -19: 
      -20: 
      -21: 
      -22: 
      -23: 
      -24: 
      -25: 
      -26: 
      -27: 
      -28: 
      -29: 
      -30: 
      -31: 
      -32: 
      -33: 
      -34: 
      -35: 
      -36: 
      -37: 
      -38: 
      -
      // Copy of an existing matrix (can also be sparse or diagonal)
      +
      // Copy of an existing matrix (can also be sparse or diagonal)
       Matrix<double> x = ...
       M.DenseOfMatrix(x);
       
      @@ -263,24 +267,7 @@ M.DenseOfMatrixArray(x);
       

      Very similar variants also exist for sparse and diagonal matrices, prefixed with Sparse and Diagonal respectively.

      The approach for vectors is exactly the same:

      - -
       1: 
      - 2: 
      - 3: 
      - 4: 
      - 5: 
      - 6: 
      - 7: 
      - 8: 
      - 9: 
      -10: 
      -11: 
      -12: 
      -13: 
      -14: 
      -15: 
      -16: 
      -
      // Standard-distributed random vector of length 10
      +
      // Standard-distributed random vector of length 10
       V.Random(10);
       
       // All-zero vector of length 10
      @@ -299,104 +286,59 @@ V.Dense(x);
       

      Creating matrices and vectors in F#

      In F# we can use the builders just like in C#, but we can also use the F# modules:

      - - - -
       1: 
      - 2: 
      - 3: 
      - 4: 
      - 5: 
      - 6: 
      - 7: 
      - 8: 
      - 9: 
      -10: 
      -11: 
      -12: 
      -13: 
      -14: 
      -15: 
      -16: 
      -17: 
      -18: 
      -19: 
      -20: 
      -21: 
      -22: 
      -23: 
      -24: 
      -25: 
      -
      let m1 = matrix [[ 2.0; 3.0 ]
      -                 [ 4.0; 5.0 ]]
      +
      let m1 = matrix [[ 2.0; 3.0 ]
      +                 [ 4.0; 5.0 ]]
       
      -let v1 = vector [ 1.0; 2.0; 3.0 ]
      +let v1 = vector [ 1.0; 2.0; 3.0 ]
       
       // dense 3x4 matrix filled with zeros.
       // (usually the type is inferred, but not for zero matrices)
      -let m2 = DenseMatrix.zero<float> 3 4
      +let m2 = DenseMatrix.zero<float> 3 4
       
       // dense 3x4 matrix initialized by a function
      -let m3 = DenseMatrix.init 3 4 (fun i j -> float (i+j))
      +let m3 = DenseMatrix.init 3 4 (fun i j -> float (i+j))
       
       // diagonal 4x4 identity matrix of single precision
      -let m4 = DiagonalMatrix.identity<float32> 4
      +let m4 = DiagonalMatrix.identity<float32> 4
       
       // dense 3x4 matrix created from a sequence of sequence-columns
      -let x = Seq.init 4 (fun c -> Seq.init 3 (fun r -> float (100*r + c)))
      -let m5 = DenseMatrix.ofColumnSeq x
      +let x = Seq.init 4 (fun c -> Seq.init 3 (fun r -> float (100*r + c)))
      +let m5 = DenseMatrix.ofColumnSeq x
       
       // random matrix with standard distribution:
      -let m6 = DenseMatrix.randomStandard<float> 3 4
      +let m6 = DenseMatrix.randomStandard<float> 3 4
       
       // random matrix with a uniform and one with a Gamma distribution:
      -let m7a = DenseMatrix.random<float> 3 4 (ContinuousUniform(-2.0, 4.0))
      -let m7b = DenseMatrix.random<float> 3 4 (Gamma(1.0, 2.0))
      -
      +let m7a = DenseMatrix.random<float> 3 4 (ContinuousUniform(-2.0, 4.0)) +let m7b = DenseMatrix.random<float> 3 4 (Gamma(1.0, 2.0)) +

      Or using any other of all the available functions.

      Arithmetics

      All the common arithmetic operators like +, -, *, / and % are provided, between matrices, vectors and scalars. In F# there are additional pointwise operators .*, ./ and .% available for convenience.

      - - - -
      1: 
      -2: 
      -3: 
      -4: 
      -5: 
      -6: 
      -7: 
      -8: 
      -
      let m = matrix [[ 1.0; 4.0; 7.0 ]
      -                [ 2.0; 5.0; 8.0 ]
      -                [ 3.0; 6.0; 9.0 ]]
      +
      let m = matrix [[ 1.0; 4.0; 7.0 ]
      +                [ 2.0; 5.0; 8.0 ]
      +                [ 3.0; 6.0; 9.0 ]]
       
      -let v = vector [ 10.0; 20.0; 30.0 ]
      +let v = vector [ 10.0; 20.0; 30.0 ]
       
      -let v' = m * v
      -let m' = m + 2.0*m
      -
      +let v' = m * v +let m' = m + 2.0*m +

      Arithmetic Instance Methods

      All other operations are covered by methods, like Transpose and Conjugate, or in F# as functions in the Matrix module, e.g. Matrix.transpose. But even the operators have equivalent methods. The equivalent code from above when using instance methods:

      - -
      1: 
      -2: 
      -
      var v2 = m.Multiply(v);
      +
      var v2 = m.Multiply(v);
       var m2 = m.Add(m.Multiply(2));
       

      These methods also have an overload that accepts the result data structure as last argument, allowing to avoid allocating new structures for every single operation. Provided the dimensions match, most also allow one of the arguments to be passed as result, resulting in an in-place application. For example, an in-place version of the code above:

      - -
      1: 
      -2: 
      -
      m.Multiply(v, v); // v <- m*v
      +
      m.Multiply(v, v); // v <- m*v
       m.Multiply(3, m); // m <- 3*m
       

      Shortcut Methods

      @@ -404,23 +346,14 @@ m.Multiply(3, m); // m <- 3*m \(\mathbf{X}^T\mathbf y = \mathbf{X}^T\mathbf X \mathbf p\) which we would like to solve for \(p\). By matrix inversion we get \(\mathbf p = (\mathbf{X}^T\mathbf X)^{-1}(\mathbf{X}^T\mathbf y)\). This can directly be translated to the following code:

      - -
      1: 
      -
      (X.Transpose() * X).Inverse() * (X.Transpose() * y)
      +
      (X.Transpose() * X).Inverse() * (X.Transpose() * y)
       

      Since products where one of the arguments is transposed are common, there are a few shortcut routines that are more efficient:

      - -
      1: 
      -
      X.TransposeThisAndMultiply(X).Inverse() * X.TransposeThisAndMultiply(y)
      +
      X.TransposeThisAndMultiply(X).Inverse() * X.TransposeThisAndMultiply(y)
       

      Of course in practice you would not use the matrix inverse but a decomposition:

      - -
      1: 
      -2: 
      -3: 
      -4: 
      -
      X.TransposeThisAndMultiply(X).Cholesky().Solve(X.TransposeThisAndMultiply(y))
      +
      X.TransposeThisAndMultiply(X).Cholesky().Solve(X.TransposeThisAndMultiply(y))
       
       // or if the problem is small enough, simply:
       X.Solve(y);
      @@ -464,9 +397,7 @@ is said to be well-conditioned, with a high condition number ill-co
       For a linear equation \(Ax=b\) the condition number is the maximum ratio of the
       relative error in \(x\) divided by the relative error in \(b\). It therefore gives a bound on how
       inaccurate the solution \(x\) will be after approximation.

      - -
      1: 
      -
      M.Random(4,4).ConditionNumber(); // e.g. 14.829
      +
      M.Random(4,4).ConditionNumber(); // e.g. 14.829
       

      Trace and Determinant

      For a square matrix, the trace of a matrix is the sum of the elements on the main diagonal, @@ -475,14 +406,7 @@ of a square matrix is the product of all its eigenvalues with multiplicities. A matrix is said to be singular if its determinant is zero and non-singular otherwise. In the latter case the matrix is invertible and the linear equation system it represents has a single unique solution.

      - -
      1: 
      -2: 
      -3: 
      -4: 
      -5: 
      -6: 
      -
      var m = M.DenseOfArray(new[,] {{ 1.0,  2.0, 1.0},
      +
      var m = M.DenseOfArray(new[,] {{ 1.0,  2.0, 1.0},
                                      {-2.0, -3.0, 1.0},
                                      { 3.0,  5.0, 0.0}});
       
      @@ -494,11 +418,7 @@ m.Determinant(); // ~0 hence not invertible, either none or mult
       number of linearly independent column and row vectors of the matrix. It is a measure
       of the non-degenerateness of the linear equation system the matrix represents.

      An orthonormal basis of the column space can be computed with the range method.

      - -
      1: 
      -2: 
      -3: 
      -
      // with the same m as above
      +
      // with the same m as above
       m.Rank();  // 2
       m.Range(); // [-0.30519,0.503259,-0.808449], [-0.757315,-0.64296,-0.114355]
       
      @@ -507,14 +427,7 @@ m.Range(); // [-0.30519,0.503259,-0.808449], [-0.757315,-0.64296 It is the orthogonal complement to the row space of the matrix.

      The nullity of a matrix is the dimension of its null space. An orthonormal basis of the null space can be computed with the kernel method.

      - -
      1: 
      -2: 
      -3: 
      -4: 
      -5: 
      -6: 
      -
      // with the same m as above
      +
      // with the same m as above
       m.Nullity(); // 1
       m.Kernel();  // [0.845154,-0.507093,0.169031]
       
      @@ -554,14 +467,7 @@ If the symmetricity of the matrix is known, the algorithm can optionally skip it
       

      Individual values can be get and set in matrices and vectors using the indexers or the At methods. Using At instead of the indexers is slightly faster but skips some range checks, so use it only after checking the range yourself.

      - -
      1: 
      -2: 
      -3: 
      -4: 
      -5: 
      -6: 
      -
      var m = Matrix<double>.Build.Dense(3,4,(i,j) => 10*i + j);
      +
      var m = Matrix<double>.Build.Dense(3,4,(i,j) => 10*i + j);
       m[0,0]; // 0   (row 0, column 0)
       m[2,0]; // 20 (row 2, column 0)
       m[0,2]; // 2   (row 0, column 2)
      @@ -569,73 +475,39 @@ m[0,2] = 0,2]; // -1
       

      In F#:

      - - - -
      1: 
      -
      m.[2,0] // 20
      -
      +
      m.[2,0] // 20
      +

      We can also get entire column or row vectors, or a new matrix from parts of an existing one.

      - -
      1: 
      -2: 
      -3: 
      -4: 
      -
      var m = M.Dense(6,4,(i,j) => 10*i + j);
      +
      var m = M.Dense(6,4,(i,j) => 10*i + j);
       m.Column(2);          // [2,12,22,32,42,52]
       m.Row(3);             // [30,31,32,33]
       m.SubMatrix(1,2,1,2); // [11,12; 21,22]
       

      For each of these methods there is also a variant prefixed with Set that can be used to overwrite those elements with the provided data.

      - -
      1: 
      -
      m.SetRow(3, V.Random(4));
      +
      m.SetRow(3, V.Random(4));
       

      In F# we can also use its slicing syntax:

      - - - -
      1: 
      -2: 
      -3: 
      -4: 
      -5: 
      -
      let m = DenseMatrix.init 6 4 (fun i j -> float (10*i + j))
      -m.[0,0..3]    // vector [0,1,2,3]
      -m.[1..2,0..3] // matrix [10,11,12,13; 20,21,22,23]
      +
      let m = DenseMatrix.init 6 4 (fun i j -> float (10*i + j))
      +m.[0,0..3]    // vector [0,1,2,3]
      +m.[1..2,0..3] // matrix [10,11,12,13; 20,21,22,23]
       // overwrite a sub-matrix with the content of another matrix:
      -m.[0..1,1..2] <- matrix [[ 3.0; 4.0 ]; [ 5.0; 6.0 ]]
      -
      +m.[0..1,1..2] <- matrix [[ 3.0; 4.0 ]; [ 5.0; 6.0 ]] +

      To set the whole matrix or some of its columns or rows to zero, use one of the clear methods:

      - -
      1: 
      -2: 
      -3: 
      -4: 
      -
      m.Clear(); // set all elements to 0
      +
      m.Clear(); // set all elements to 0
       m.ClearColumn(2); // set the 3rd column to 0 (0-based indexing)
       m.ClearColumns(1,3); // set the 2nd and 4th columns to 0 (params-array)
       m.ClearSubMatrix(1,2,1,2); // set the 2x2 submatrix with offset 1,1 to zero
       

      Because of the limitations of floating point numbers, we may want to set very small numbers to zero:

      - -
      1: 
      -2: 
      -
      m.CoerceZero(1e-14); // set all elements smaller than 1e-14 to 0
      +
      m.CoerceZero(1e-14); // set all elements smaller than 1e-14 to 0
       m.CoerceZero(x => x < 10); // set all elements that match a predicate function to 0.
       

      Even though matrices and vectors are mutable, their dimension is fixed and cannot be changed after creation. However, we can still insert or remove rows or columns, or concatenate matrices together. But all these operations will create and return a new instance.

      - -
      1: 
      -2: 
      -3: 
      -4: 
      -5: 
      -6: 
      -
      var m2 = m.RemoveRow(2); // remove the 3rd rows
      +
      var m2 = m.RemoveRow(2); // remove the 3rd rows
       var m3 = m2.RemoveColumn(3); // remove the 4th column
       
       var m4 = m.Stack(m2); // new matrix with m on top and m2 on the bottom
      @@ -679,21 +551,13 @@ of applying a function to its value. Or, if indexed, to its index and value.

    • MapIndexed(f,zeros): indexed variant of Map.
    • Example: Convert a complex vector to a real vector containing only the real parts in C#:

      - -
      1: 
      -2: 
      -
      Vector<Complex> u = Vector<Complex>.Build.Random(10);
      +
      Vector<Complex> u = Vector<Complex>.Build.Random(10);
       Vector<Double> v = u.Map(c => c.Real);
       

      Or in F#:

      - - - -
      1: 
      -2: 
      -
      let u = DenseVector.randomStandard<Complex> 10
      -let v = u |> Vector.map (fun c -> c.Real)
      -
      +
      let u = DenseVector.randomStandard<Complex> 10
      +let v = u |> Vector.map (fun c -> c.Real)
      +

      Fold and Reduce

      Matrices also provide column/row fold and reduce routines:

        @@ -708,43 +572,7 @@ in a reasonable way, without overflowing the output device on a large matrix.

        Some matrix examples:

        - -
         1: 
        - 2: 
        - 3: 
        - 4: 
        - 5: 
        - 6: 
        - 7: 
        - 8: 
        - 9: 
        -10: 
        -11: 
        -12: 
        -13: 
        -14: 
        -15: 
        -16: 
        -17: 
        -18: 
        -19: 
        -20: 
        -21: 
        -22: 
        -23: 
        -24: 
        -25: 
        -26: 
        -27: 
        -28: 
        -29: 
        -30: 
        -31: 
        -32: 
        -33: 
        -34: 
        -35: 
        -
        // Matrix<double>.Build.Dense(3,4,(i,j) => i*10*j).ToString()
        +
        // Matrix<double>.Build.Dense(3,4,(i,j) => i*10*j).ToString()
         DenseMatrix 3x4-Double
         0   0   0   0
         0  10  20  30
        @@ -781,37 +609,7 @@ SparseMatrix 4x100-Double 0.25% Filled
         0  0    0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  ..  0  0
         

        Vectors are printed as a column that can wrap over to multiple columns if needed:

        - -
         1: 
        - 2: 
        - 3: 
        - 4: 
        - 5: 
        - 6: 
        - 7: 
        - 8: 
        - 9: 
        -10: 
        -11: 
        -12: 
        -13: 
        -14: 
        -15: 
        -16: 
        -17: 
        -18: 
        -19: 
        -20: 
        -21: 
        -22: 
        -23: 
        -24: 
        -25: 
        -26: 
        -27: 
        -28: 
        -29: 
        -
        // Vector<double>.Build.Random(15).ToString()
        +
        // Vector<double>.Build.Random(15).ToString()
         DenseVector 15-Double
          0.519184  0.0950414
           1.65913    2.56783
        @@ -843,42 +641,7 @@ DenseVector 500-Double
         

        The format is customizable to some degree, for example we can choose the floating point format and culture, or how many rows or columns should be shown:

        - -
         1: 
        - 2: 
        - 3: 
        - 4: 
        - 5: 
        - 6: 
        - 7: 
        - 8: 
        - 9: 
        -10: 
        -11: 
        -12: 
        -13: 
        -14: 
        -15: 
        -16: 
        -17: 
        -18: 
        -19: 
        -20: 
        -21: 
        -22: 
        -23: 
        -24: 
        -25: 
        -26: 
        -27: 
        -28: 
        -29: 
        -30: 
        -31: 
        -32: 
        -33: 
        -34: 
        -
        // var m = Matrix<double>.Build.Random(5,100,42); // 42 = random seed
        +
        // var m = Matrix<double>.Build.Random(5,100,42); // 42 = random seed
         
         // m.ToString()
         DenseMatrix 5x100-Double
        @@ -917,112 +680,99 @@ DenseMatrix 5x100-Double
         to load the MathNet.Numerics.fsx script of the F# package. Besides loading
         the assemblies it also adds proper FSI printers for both matrices and vectors.

        -
        val m1 : obj

        Full name: Matrix.m1
        -
        val v1 : obj

        Full name: Matrix.v1
        -
        val m2 : obj

        Full name: Matrix.m2
        -
        Multiple items
        val float : value:'T -> float (requires member op_Explicit)

        Full name: Microsoft.FSharp.Core.Operators.float

        --------------------
        type float = System.Double

        Full name: Microsoft.FSharp.Core.float

        --------------------
        type float<'Measure> = float

        Full name: Microsoft.FSharp.Core.float<_>
        -
        val m3 : obj

        Full name: Matrix.m3
        -
        val m4 : obj

        Full name: Matrix.m4
        -
        Multiple items
        val float32 : value:'T -> float32 (requires member op_Explicit)

        Full name: Microsoft.FSharp.Core.Operators.float32

        --------------------
        type float32 = System.Single

        Full name: Microsoft.FSharp.Core.float32

        --------------------
        type float32<'Measure> = float32

        Full name: Microsoft.FSharp.Core.float32<_>
        -
        val x : seq<seq<float>>

        Full name: Matrix.x
        -
        module Seq

        from Microsoft.FSharp.Collections
        -
        val init : count:int -> initializer:(int -> 'T) -> seq<'T>

        Full name: Microsoft.FSharp.Collections.Seq.init
        -
        val c : int
        -
        val r : int
        -
        val m5 : obj

        Full name: Matrix.m5
        -
        val m6 : obj

        Full name: Matrix.m6
        -
        val m7a : obj

        Full name: Matrix.m7a
        -
        val m7b : obj

        Full name: Matrix.m7b
        -
        val m : float

        Full name: Matrix.m
        -
        val v : float

        Full name: Matrix.v
        -
        val v' : float

        Full name: Matrix.v'
        -
        val m' : float

        Full name: Matrix.m'
        -
        val m : obj

        Full name: Matrix.m
        -
        val u : obj

        Full name: Matrix.u
        -
        Multiple items
        type Complex =
          struct
            new : real:float * imaginary:float -> Complex
            member Equals : obj:obj -> bool + 1 overload
            member GetHashCode : unit -> int
            member Imaginary : float
            member Magnitude : float
            member Phase : float
            member Real : float
            member ToString : unit -> string + 3 overloads
            static val Zero : Complex
            static val One : Complex
            ...
          end

        Full name: System.Numerics.Complex

        --------------------
        Complex()
        Complex(real: float, imaginary: float) : unit
        -
        val v : obj

        Full name: Matrix.v
        - - -
        - -
        - - + + + + + + + + + + diff --git a/MatrixMarket.html b/MatrixMarket.html index f373f587..84dd282a 100644 --- a/MatrixMarket.html +++ b/MatrixMarket.html @@ -1,63 +1,138 @@ - - - NIST MatrixMarket Text Files + +<head> + <meta charset="utf-8"> + <title>NIST MatrixMarket Text Files - - - - - - - - - - - - - - - - - - -
        -
        - -

        Math.NET Numerics

        + + + + + + + + + + + + + + + + + + + + + + + + +
        + +
        +
        +

        NIST MatrixMarket Text Files

        MatrixMarket is both a vast repository of test data and a text-based exchange file format provided by NIST. Being text-based makes it convenient to deal with and program against, and also works well with versioning @@ -78,11 +153,7 @@ you can use this method using a StringReader.

        All these functions expect the data type of the matrix to be generated as generic type argument. Only Double, Single, Complex and Complex32 are supported.

        Example:

        - -
        1: 
        -2: 
        -3: 
        -
        using MathNet.Numerics.Data.Text;
        +
        using MathNet.Numerics.Data.Text;
         
         Matrix<double> matrix = MatrixMarketReader.ReadMatrix<double>("fidap007.mtx");
         
        @@ -90,9 +161,7 @@ Matrix<double> matrix = Matr

        The dual to the reader above is the MatrixMarketWriter class that can serialize a matrix or vector to a MatrixMarket text file, stream or TextWriter.

        Example:

        - -
        1: 
        -
        MatrixMarketWriter.WriteMatrix("matrix.mtx", m);
        +
        MatrixMarketWriter.WriteMatrix("matrix.mtx", m);
         

        Alternatives

        The data extension packages also offer other ways to serialize a matrix to a binary stream or file. @@ -102,88 +171,16 @@ Among others:

      • MATLAB Level-5 Mat files
      • - - -
        - -
        - + - + + + + + + + + + + diff --git a/NuGet.config b/NuGet.config new file mode 100644 index 00000000..cf1ace51 --- /dev/null +++ b/NuGet.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Packages.html b/Packages.html index df473baf..20b5b4c1 100644 --- a/Packages.html +++ b/Packages.html @@ -1,63 +1,138 @@ - - - NuGet Packages & Binaries + +<head> + <meta charset="utf-8"> + <title>NuGet Packages & Binaries - - - - - - - - - - - - - - - - - - -
        -
        - -

        Math.NET Numerics

        + + + + + + + + + + + + + + + + + + + + + + + + +
        + +
        +
        +

        NuGet Packages & Binaries

        The recommended way to get Math.NET Numerics is NuGet. The following packages are provided and maintained in the public NuGet Gallery. The complete set of Zip and NuGet packages including symbol packages is also available in the @@ -102,88 +177,16 @@ it may be easier to download the Zip file in the MathNet.Numerics.Data.Matlab - MATLAB Level-5 matrix file format. - -

        -
        - -
        -
        +
        - + + + + + + + +
        + + diff --git a/Probability.html b/Probability.html index 90ee17b4..cbb7d385 100644 --- a/Probability.html +++ b/Probability.html @@ -1,63 +1,138 @@ - - - Probability Distributions + +<head> + <meta charset="utf-8"> + <title>Probability Distributions - - - - - - - - - - - - - - - - - - -
        -
        - -

        Math.NET Numerics

        + + + + + + + + + + + + + + + + + + + + + + + + +
        + +
        +
        +

        Probability Distributions

        Math.NET Numerics provides a wide range of probability distributions. Given the distribution parameters they can be used to investigate their statistical properties or to sample non-uniform random numbers.

        @@ -67,26 +142,7 @@ at a given point, or to compute the mean, standard deviation and other propertie Because it is often numerically more stable and faster to compute such statistical quantities in the logarithmic domain, we also provide a selection of them in the log domain with the "Ln" suffix, e.g. DensityLn for the logarithmic density.

        - -
         1: 
        - 2: 
        - 3: 
        - 4: 
        - 5: 
        - 6: 
        - 7: 
        - 8: 
        - 9: 
        -10: 
        -11: 
        -12: 
        -13: 
        -14: 
        -15: 
        -16: 
        -17: 
        -18: 
        -
        using MathNet.Numerics.Distributions;
        +
        using MathNet.Numerics.Distributions;
         using MathNet.Numerics.Random;
         
         // create a parametrized distribution instance
        @@ -107,11 +163,7 @@ e.g. DensityLn for the logarithmic density.

        Both probability functions and sampling are also available as static functions for simpler usage scenarios:

        - -
        1: 
        -2: 
        -3: 
        -
        // distribution parameters must be passed as arguments
        +
        // distribution parameters must be passed as arguments
         double a2 = Gamma.PDF(2.0, 1.5, 2.3);
         double randomSample2 = Gamma.Sample(2.0, 1.5);
         
        @@ -171,60 +223,33 @@ default constructor, read carefully which parameters it requires. For distributi multiple ways are common there are also static methods, so you can use the one that fits best. For example, a normal distribution is usually parametrized with mean and standard deviation, but if you'd rather use mean and precision:

        - -
        1: 
        -
        var normal = Normal.WithMeanPrecision(0.0, 0.5);
        +
        var normal = Normal.WithMeanPrecision(0.0, 0.5);
         

        Since probability distributions can also be sampled to generate random numbers with the configured distribution, all constructors optionally accept a random generator as last argument.

        - -
        1: 
        -2: 
        -3: 
        -4: 
        -
        var gamma2 = new Gamma(2.0, 1.5, new MersenneTwister());
        +
        var gamma2 = new Gamma(2.0, 1.5, new MersenneTwister());
         
         // the random generator can also be replaced on an existing instance
         gamma2.RandomSource = new Mrg32k3a();
         

        A few more examples, this time in F#:

        - - - -
        1: 
        -2: 
        -3: 
        -4: 
        -5: 
        -6: 
        -7: 
        -
        // some probability distributions
        -let normal = Normal.WithMeanVariance(3.0, 1.5, a)
        -let exponential = Exponential(2.4)
        -let gamma = Gamma(2.0, 1.5, Random.crypto())
        -let cauchy = Cauchy(0.0, 1.0, Random.mrg32k3aWith 10 false)
        -let poisson = Poisson(3.0)
        -let geometric = Geometric(0.8, Random.system())
        -
        +
        // some probability distributions
        +let normal = Normal.WithMeanVariance(3.0, 1.5, a)
        +let exponential = Exponential(2.4)
        +let gamma = Gamma(2.0, 1.5, Random.crypto())
        +let cauchy = Cauchy(0.0, 1.0, Random.mrg32k3aWith 10 false)
        +let poisson = Poisson(3.0)
        +let geometric = Geometric(0.8, Random.system())
        +

        Some of the distributions also have routines for maximum-likelihood parameter estimation from a set of samples:

        - - - -
        1: 
        -2: 
        -3: 
        -
        let estimation = LogNormal.Estimate([| 2.0; 1.5; 2.1; 1.2; 3.0; 2.4; 1.8 |])
        -let mean, variance = estimation.Mean, estimation.Variance
        -let moreSamples = estimation.Samples() |> Seq.take 10 |> Seq.toArray
        -
        +
        let estimation = LogNormal.Estimate([| 2.0; 1.5; 2.1; 1.2; 3.0; 2.4; 1.8 |])
        +let mean, variance = estimation.Mean, estimation.Variance
        +let moreSamples = estimation.Samples() |> Seq.take 10 |> Seq.toArray
        +

        or in C#:

        - -
        1: 
        -2: 
        -3: 
        -
        LogNormal estimation = LogNormal.Estimate(new [] {2.0, 1.5, 2.1, 1.2, 3.0, 2.4, 1.8});
        +
        LogNormal estimation = LogNormal.Estimate(new [] {2.0, 1.5, 2.1, 1.2, 3.0, 2.4, 1.8});
         double mean = estimation.Mean, variance = estimation.Variance;
         double[] moreSamples = estimation.Samples().Take(10).ToArray();
         
        @@ -234,289 +259,166 @@ These random variate generators work by accessing the distribution's member Rand to provide uniform random numbers. By default, this member is an instance of System.Random but one can easily replace this with more sophisticated random number generators from MathNet.Numerics.Random (see Random Numbers for details).

        - - - -
         1: 
        - 2: 
        - 3: 
        - 4: 
        - 5: 
        - 6: 
        - 7: 
        - 8: 
        - 9: 
        -10: 
        -11: 
        -12: 
        -
        // sample some random numbers from these distributions
        +
        // sample some random numbers from these distributions
         // continuous distributions sample to floating-point numbers:
        -let continuous =
        -  [ yield normal.Sample()
        -    yield exponential.Sample()
        -    yield! gamma.Samples() |> Seq.take 10 ]
        +let continuous =
        +  [ yield normal.Sample()
        +    yield exponential.Sample()
        +    yield! gamma.Samples() |> Seq.take 10 ]
         
         // discrete distributions on the other hand sample to integers:
        -let discrete =
        -  [ poisson.Sample()
        -    poisson.Sample()
        -    geometric.Sample() ]
        -
        +let discrete = + [ poisson.Sample() + poisson.Sample() + geometric.Sample() ] +

        Instead of creating a distribution object we can also sample directly with static functions. Note that no intermediate value caching is possible this way and parameters must be validated on each call.

        - - - -
        1: 
        -2: 
        -3: 
        -4: 
        -5: 
        -6: 
        -7: 
        -
        // using the default number generator (SystemRandomSource.Default)
        -let w = Rayleigh.Sample(1.5)
        -let x = Hypergeometric.Sample(100, 20, 5)
        +
        // using the default number generator (SystemRandomSource.Default)
        +let w = Rayleigh.Sample(1.5)
        +let x = Hypergeometric.Sample(100, 20, 5)
         
         // or by manually providing the uniform random number generator
        -let u = Normal.Sample(Random.system(), 2.0, 4.0)
        -let v = Laplace.Samples(Random.mersenneTwister(), 1.0, 3.0) |> Seq.take 100 |> List.ofSeq
        -
        +let u = Normal.Sample(Random.system(), 2.0, 4.0) +let v = Laplace.Samples(Random.mersenneTwister(), 1.0, 3.0) |> Seq.take 100 |> List.ofSeq +

        If you need to sample not just one or two values but a large number of them, there are routines that either fill an existing array or return an enumerable. The variant that fills an array is generally the fastest. Routines to sample more than one value use the plural form Samples instead of Sample.

        Let's sample 100'000 values from a laplace distribution with mean 1.0 and scale 2.0 in C#:

        - -
        1: 
        -2: 
        -
        var samples = new double[100000];
        +
        var samples = new double[100000];
         Laplace.Samples(samples, 1.0, 2.0);
         

        Let's do some random walks in F# (TODO: Graph):

        - - - -
        1: 
        -2: 
        -
        Seq.scan (+) 0.0 (Normal.Samples(0.0, 1.0)) |> Seq.take 10 |> Seq.toArray
        -Seq.scan (+) 0.0 (Cauchy.Samples(0.0, 1.0)) |> Seq.take 10 |> Seq.toArray
        -
        +
        Seq.scan (+) 0.0 (Normal.Samples(0.0, 1.0)) |> Seq.take 10 |> Seq.toArray
        +Seq.scan (+) 0.0 (Cauchy.Samples(0.0, 1.0)) |> Seq.take 10 |> Seq.toArray
        +

        Distribution Functions and Properties

        Distributions can not just be used to generate non-uniform random samples. Once parametrized they can compute a variety of distribution properties or evaluate distribution functions. Because it is often numerically more stable and faster to compute and work with such quantities in the logarithmic domain, some of them are also available with the Ln-suffix.

        - - - -
         1: 
        - 2: 
        - 3: 
        - 4: 
        - 5: 
        - 6: 
        - 7: 
        - 8: 
        - 9: 
        -10: 
        -11: 
        -12: 
        -13: 
        -14: 
        -15: 
        -16: 
        -17: 
        -18: 
        -19: 
        -20: 
        -21: 
        -
        // distribution properties of the gamma we've configured above
        -let gammaStats =
        -  ( gamma.Mean,
        -    gamma.Variance,
        -    gamma.StdDev,
        -    gamma.Entropy,
        -    gamma.Skewness,
        -    gamma.Mode )
        +
        // distribution properties of the gamma we've configured above
        +let gammaStats =
        +  ( gamma.Mean,
        +    gamma.Variance,
        +    gamma.StdDev,
        +    gamma.Entropy,
        +    gamma.Skewness,
        +    gamma.Mode )
         
         // probability distribution functions of the normal we've configured above.
        -let nd = normal.Density(4.0)  (* PDF *)
        -let ndLn = normal.DensityLn(4.0)  (* ln(PDF) *)
        -let nc = normal.CumulativeDistribution(4.0)  (* CDF *)
        -let nic = normal.InverseCumulativeDistribution(0.7)  (* CDF^(-1) *)
        +let nd = normal.Density(4.0)  (* PDF *)
        +let ndLn = normal.DensityLn(4.0)  (* ln(PDF) *)
        +let nc = normal.CumulativeDistribution(4.0)  (* CDF *)
        +let nic = normal.InverseCumulativeDistribution(0.7)  (* CDF^(-1) *)
         
         // Distribution functions can also be evaluated without creating an object,
         // but then you have to pass in the distribution parameters as first arguments:
        -let nd2 = Normal.PDF(3.0, sqrt 1.5, 4.0)
        -let ndLn2 = Normal.PDFLn(3.0, sqrt 1.5, 4.0)
        -let nc2 = Normal.CDF(3.0, sqrt 1.5, 4.0)
        -let nic2 = Normal.InvCDF(3.0, sqrt 1.5, 0.7)
        -
        +let nd2 = Normal.PDF(3.0, sqrt 1.5, 4.0) +let ndLn2 = Normal.PDFLn(3.0, sqrt 1.5, 4.0) +let nc2 = Normal.CDF(3.0, sqrt 1.5, 4.0) +let nic2 = Normal.InvCDF(3.0, sqrt 1.5, 0.7) +

        Composing Distributions

        Specifically for F# there is also a Sample module that allows a somewhat more functional view on distribution sampling functions by having the random source passed in as last argument. This way they can be composed and transformed arbitrarily if curried:

        - - - -
         1: 
        - 2: 
        - 3: 
        - 4: 
        - 5: 
        - 6: 
        - 7: 
        - 8: 
        - 9: 
        -10: 
        -11: 
        -12: 
        -13: 
        -14: 
        -15: 
        -16: 
        -
        /// Transform a sample from a distribution
        -let s1 rng = tanh (Sample.normal 2.0 0.5 rng)
        +
        /// Transform a sample from a distribution
        +let s1 rng = tanh (Sample.normal 2.0 0.5 rng)
         
         /// But we really want to transform the function, not the resulting sample:
        -let s1f rng = Sample.map tanh (Sample.normal 2.0 0.5) rng
        +let s1f rng = Sample.map tanh (Sample.normal 2.0 0.5) rng
         
         /// Exactly the same also works with functions generating full sequences
        -let s1s rng = Sample.mapSeq tanh (Sample.normalSeq 2.0 0.5) rng
        +let s1s rng = Sample.mapSeq tanh (Sample.normalSeq 2.0 0.5) rng
         
         /// Now with multiple distributions, e.g. their product:
        -let s2 rng = (Sample.normal 2.0 1.5 rng) * (Sample.cauchy 2.0 0.5 rng)
        -let s2f rng = Sample.map2 (*) (Sample.normal 2.0 1.5) (Sample.cauchy 2.0 0.5) rng
        -let s2s rng = Sample.mapSeq2 (*) (Sample.normalSeq 2.0 1.5) (Sample.cauchySeq 2.0 0.5) rng
        +let s2 rng = (Sample.normal 2.0 1.5 rng) * (Sample.cauchy 2.0 0.5 rng)
        +let s2f rng = Sample.map2 (*) (Sample.normal 2.0 1.5) (Sample.cauchy 2.0 0.5) rng
        +let s2s rng = Sample.mapSeq2 (*) (Sample.normalSeq 2.0 1.5) (Sample.cauchySeq 2.0 0.5) rng
         
         // Taking some samples from the composed function
        -Seq.take 10 (s2s (Random.system())) |> Seq.toArray
        -
        - -
        val normal : obj

        Full name: Probability.normal
        -
        val exponential : obj

        Full name: Probability.exponential
        -
        val gamma : obj

        Full name: Probability.gamma
        -
        val cauchy : obj

        Full name: Probability.cauchy
        -
        val poisson : obj

        Full name: Probability.poisson
        -
        val geometric : obj

        Full name: Probability.geometric
        -
        val estimation : obj

        Full name: Probability.estimation
        -
        val mean : obj

        Full name: Probability.mean
        -
        val variance : obj

        Full name: Probability.variance
        -
        val moreSamples : obj []

        Full name: Probability.moreSamples
        -
        module Seq

        from Microsoft.FSharp.Collections
        -
        val take : count:int -> source:seq<'T> -> seq<'T>

        Full name: Microsoft.FSharp.Collections.Seq.take
        -
        val toArray : source:seq<'T> -> 'T []

        Full name: Microsoft.FSharp.Collections.Seq.toArray
        -
        val continuous : obj list

        Full name: Probability.continuous
        -
        val discrete : obj list

        Full name: Probability.discrete
        -
        val w : obj

        Full name: Probability.w
        -
        val x : obj

        Full name: Probability.x
        -
        val u : obj

        Full name: Probability.u
        -
        val v : obj list

        Full name: Probability.v
        -
        Multiple items
        module List

        from Microsoft.FSharp.Collections

        --------------------
        type List<'T> =
          | ( [] )
          | ( :: ) of Head: 'T * Tail: 'T list
          interface IEnumerable
          interface IEnumerable<'T>
          member GetSlice : startIndex:int option * endIndex:int option -> 'T list
          member Head : 'T
          member IsEmpty : bool
          member Item : index:int -> 'T with get
          member Length : int
          member Tail : 'T list
          static member Cons : head:'T * tail:'T list -> 'T list
          static member Empty : 'T list

        Full name: Microsoft.FSharp.Collections.List<_>
        -
        val ofSeq : source:seq<'T> -> 'T list

        Full name: Microsoft.FSharp.Collections.List.ofSeq
        -
        val scan : folder:('State -> 'T -> 'State) -> state:'State -> source:seq<'T> -> seq<'State>

        Full name: Microsoft.FSharp.Collections.Seq.scan
        -
        val gammaStats : obj * obj * obj * obj * obj * obj

        Full name: Probability.gammaStats
        -
        val nd : obj

        Full name: Probability.nd
        -
        val ndLn : obj

        Full name: Probability.ndLn
        -
        val nc : obj

        Full name: Probability.nc
        -
        val nic : obj

        Full name: Probability.nic
        -
        val nd2 : obj

        Full name: Probability.nd2
        -
        val sqrt : value:'T -> 'U (requires member Sqrt)

        Full name: Microsoft.FSharp.Core.Operators.sqrt
        -
        val ndLn2 : obj

        Full name: Probability.ndLn2
        -
        val nc2 : obj

        Full name: Probability.nc2
        -
        val nic2 : obj

        Full name: Probability.nic2
        -
        val s1 : rng:'a -> float

        Full name: Probability.s1


         Transform a sample from a distribution
        -
        val rng : 'a
        -
        val tanh : value:'T -> 'T (requires member Tanh)

        Full name: Microsoft.FSharp.Core.Operators.tanh
        -
        val s1f : rng:'a -> 'b

        Full name: Probability.s1f


         But we really want to transform the function, not the resulting sample:
        -
        val s1s : rng:'a -> 'b

        Full name: Probability.s1s


         Exactly the same also works with functions generating full sequences
        -
        val s2 : rng:'a -> obj

        Full name: Probability.s2


         Now with multiple distributions, e.g. their product:
        -
        val s2f : rng:'a -> 'b

        Full name: Probability.s2f
        -
        val s2s : rng:'a -> 'b

        Full name: Probability.s2s
        +Seq.take 10 (s2s (Random.system())) |> Seq.toArray + + +
        val normal : obj
        +
        val exponential : obj
        +
        val gamma : obj
        +
        val cauchy : obj
        +
        val poisson : obj
        +
        val geometric : obj
        +
        val estimation : obj
        +
        val mean : obj
        +
        val variance : obj
        +
        val moreSamples : obj []
        +
        Modul Seq + +aus Microsoft.FSharp.Collections
        <summary>Contains operations for working with values of type <see cref="T:Microsoft.FSharp.Collections.seq`1" />.</summary>
        +
        val take : count:int -> source:seq<'T> -> seq<'T>
        <summary>Returns the first N elements of the sequence.</summary>
        <remarks>Throws <c>InvalidOperationException</c> + if the count exceeds the number of elements in the sequence. <c>Seq.truncate</c> + returns as many items as the sequence contains instead of throwing an exception.</remarks>
        <param name="count">The number of items to take.</param>
        <param name="source">The input sequence.</param>
        <returns>The result sequence.</returns>
        <exception cref="T:System.ArgumentNullException">Thrown when the input sequence is null.</exception>
        <exception cref="T:System.ArgumentException">Thrown when the input sequence is empty.</exception>
        <exception cref="T:System.InvalidOperationException">Thrown when count exceeds the number of elements + in the sequence.</exception>
        +
        val toArray : source:seq<'T> -> 'T []
        <summary>Builds an array from the given collection.</summary>
        <param name="source">The input sequence.</param>
        <returns>The result array.</returns>
        <exception cref="T:System.ArgumentNullException">Thrown when the input sequence is null.</exception>
        +
        val continuous : obj list
        +
        val discrete : obj list
        +
        val w : obj
        +
        val x : obj
        +
        val u : obj
        +
        val v : obj list
        +
        Multiple items
        Modul List + +aus Microsoft.FSharp.Collections
        <summary>Contains operations for working with values of type <see cref="T:Microsoft.FSharp.Collections.list`1" />.</summary>
        <namespacedoc><summary>Operations for collections such as lists, arrays, sets, maps and sequences. See also + <a href="https://docs.microsoft.com/dotnet/fsharp/language-reference/fsharp-collection-types">F# Collection Types</a> in the F# Language Guide. + </summary></namespacedoc>


        --------------------
        type List<'T> = + | ( [] ) + | ( :: ) of Head: 'T * Tail: 'T list + interface IReadOnlyList<'T> + interface IReadOnlyCollection<'T> + interface IEnumerable + interface IEnumerable<'T> + member GetReverseIndex : rank:int * offset:int -> int + member GetSlice : startIndex:int option * endIndex:int option -> 'T list + static member Cons : head:'T * tail:'T list -> 'T list + member Head : 'T + member IsEmpty : bool + member Item : index:int -> 'T with get + ...
        <summary>The type of immutable singly-linked lists.</summary>
        <remarks>Use the constructors <c>[]</c> and <c>::</c> (infix) to create values of this type, or + the notation <c>[1;2;3]</c>. Use the values in the <c>List</c> module to manipulate + values of this type, or pattern match against the values directly. + </remarks>
        <exclude />
        +
        val ofSeq : source:seq<'T> -> 'T list
        <summary>Builds a new list from the given enumerable object.</summary>
        <param name="source">The input sequence.</param>
        <returns>The list of elements from the sequence.</returns>
        +
        val scan : folder:('State -> 'T -> 'State) -> state:'State -> source:seq<'T> -> seq<'State>
        <summary>Like fold, but computes on-demand and returns the sequence of intermediary and final results.</summary>
        <param name="folder">A function that updates the state with each element from the sequence.</param>
        <param name="state">The initial state.</param>
        <param name="source">The input sequence.</param>
        <returns>The resulting sequence of computed states.</returns>
        <exception cref="T:System.ArgumentNullException">Thrown when the input sequence is null.</exception>
        +
        val gammaStats : obj * obj * obj * obj * obj * obj
        +
        val nd : obj
        +
        val ndLn : obj
        +
        val nc : obj
        +
        val nic : obj
        +
        val nd2 : obj
        +
        val sqrt : value:'T -> 'U (requires member Sqrt)
        <summary>Square root of the given number</summary>
        <param name="value">The input value.</param>
        <returns>The square root of the input.</returns>
        +
        val ndLn2 : obj
        +
        val nc2 : obj
        +
        val nic2 : obj
        +
        val s1 : rng:'a -> float
         Transform a sample from a distribution
        +
        val rng : 'a
        +
        val tanh : value:'T -> 'T (requires member Tanh)
        <summary>Hyperbolic tangent of the given number</summary>
        <param name="value">The input value.</param>
        <returns>The hyperbolic tangent of the input.</returns>
        +
        val s1f : rng:'a -> 'b
         But we really want to transform the function, not the resulting sample:
        +
        val s1s : rng:'a -> 'b
         Exactly the same also works with functions generating full sequences
        +
        val s2 : rng:'a -> obj
         Now with multiple distributions, e.g. their product:
        +
        val s2f : rng:'a -> 'b
        +
        val s2s : rng:'a -> 'b
        - -
        - -
        - - + + + + + + + + + + diff --git a/Random.html b/Random.html index 377aa11c..f1c89164 100644 --- a/Random.html +++ b/Random.html @@ -1,63 +1,138 @@ - - - Pseudo-Random Numbers + +<head> + <meta charset="utf-8"> + <title>Pseudo-Random Numbers - - - - - - - - - - - - - - - - - - -
        -
        - -

        Math.NET Numerics

        + + + + + + + + + + + + + + + + + + + + + + + + +
        + +
        +
        +

        Pseudo-Random Numbers

        The .Net Framework base class library (BCL) includes a pseudo-random number generator for non-cryptography use in the form of the System.Random class. Math.NET Numerics provides a few alternatives with different characteristics @@ -73,30 +148,13 @@ distributions, like evaluating statistical distribution properties or functions.

        Initialization

        We need to reference Math.NET Numerics and open the namespaces for random numbers and probability distributions:

        - -
        1: 
        -2: 
        -
        using MathNet.Numerics.Random;
        +
        using MathNet.Numerics.Random;
         using MathNet.Numerics.Distributions;
         

        Generating Random Numbers

        Let's sample a few random values from a uniform distributed variable \(X\sim\mathcal{U}(0,1)\), such that \(0 \le x < 1\):

        - -
         1: 
        - 2: 
        - 3: 
        - 4: 
        - 5: 
        - 6: 
        - 7: 
        - 8: 
        - 9: 
        -10: 
        -11: 
        -12: 
        -13: 
        -
        // create an array with 1000 random values
        +
        // create an array with 1000 random values
         double[] samples = SystemRandomSource.Doubles(1000);
         
         // now overwrite the existing array with new random values
        @@ -111,34 +169,19 @@ System.Random rng = SystemRandomSource.Default;
         decimal sampled = rng.NextDecimal();
         

        In F# we can do exactly the same, or alternatively use the Random module:

        - - - -
         1: 
        - 2: 
        - 3: 
        - 4: 
        - 5: 
        - 6: 
        - 7: 
        - 8: 
        - 9: 
        -10: 
        -11: 
        -12: 
        -
        let samples = Random.doubles 1000
        +
        let samples = Random.doubles 1000
         
         // overwrite the whole array with new random values
        -Random.doubleFill samples
        +Random.doubleFill samples
         
         // create an infinite sequence:
        -let sampleSeq = Random.doubleSeq ()
        +let sampleSeq = Random.doubleSeq ()
         
         // take a single random value
        -let rng = Random.shared
        -let sample = rng.NextDouble()
        -let sampled = rng.NextDecimal()
        -
        +let rng = Random.shared +let sample = rng.NextDouble() +let sampled = rng.NextDecimal() +

        If you have used the .Net BCL random number generators before, you have likely noticed a few differences: we used special routines to create a full array or sequence in one go, we were able to sample a decimal number, an we used static functions @@ -146,10 +189,7 @@ and a shared default instance instead of creating our own instance.

        Math.NET Numerics provides a few alternative random number generators in their own types. For example, MersenneTwister implements the very popular mersenne twister algorithm. All these types inherit from System.Random, are fully compatible to it and can also be used exactly the same way:

        - -
        1: 
        -2: 
        -
        System.Random random = new SystemRandomSource();
        +
        System.Random random = new SystemRandomSource();
         var sample = random.NextDouble();
         

        However, unlike System.Random they can be made thread safe, use much more reasonable @@ -183,33 +223,17 @@ and is often unwanted. That's why all Math.NET Numerics RNGs are by default initialized with a robust seed taken from the CryptoRandomSource if available, or else a combination of a random number from a shared RNG, the time and a Guid (which are supposed to be generated uniquely, worldwide).

        - - - -
        1: 
        -2: 
        -3: 
        -
        let someTimeSeed = RandomSeed.Time() // not recommended
        -let someGuidSeed = RandomSeed.Guid()
        -let someRobustSeed = RandomSeed.Robust() // recommended, used by default
        -
        +
        let someTimeSeed = RandomSeed.Time() // not recommended
        +let someGuidSeed = RandomSeed.Guid()
        +let someRobustSeed = RandomSeed.Robust() // recommended, used by default
        +

        Let's generate random numbers like before, but this time with custom seed 42:

        - - - -
        1: 
        -2: 
        -3: 
        -
        let samplesSeeded = Random.doublesSeed 42 1000
        -Random.doubleFillSeed 42 samplesSeeded
        -let samplesSeqSeeded = Random.doubleSeqSeed 42
        -
        +
        let samplesSeeded = Random.doublesSeed 42 1000
        +Random.doubleFillSeed 42 samplesSeeded
        +let samplesSeqSeeded = Random.doubleSeqSeed 42
        +

        Or without the F# Random module, e.g. in C#:

        - -
        1: 
        -2: 
        -3: 
        -
        double[] samplesSeeded = SystemRandomSource.Doubles(1000, 42);
        +
        double[] samplesSeeded = SystemRandomSource.Doubles(1000, 42);
         SystemRandomSource.Doubles(samplesSeeded, 42);
         IEnumerable<double> sampleSeqSeeded = SystemRandomSource.DoubleSequence(42);
         
        @@ -228,19 +252,7 @@ IEnumerable<double> sampleSeqSeeded Palf: Parallel Additive Lagged Fibonacci generator

        Let's sample a few uniform random values using Mersenne Twister in C#:

        - -
         1: 
        - 2: 
        - 3: 
        - 4: 
        - 5: 
        - 6: 
        - 7: 
        - 8: 
        - 9: 
        -10: 
        -11: 
        -
        // Typical way with an instance:
        +
        // Typical way with an instance:
         var random = new MersenneTwister(42); // seed 42
         int sampleInt = random.Next();
         double sampleDouble = random.NextDouble();
        @@ -254,36 +266,20 @@ IEnumerable<double> sampleSeq =

        In F# you can use the constructor as well, or alternatively use the Random module. In case of the latter, all objects will be cast to their common base type System.Random:

        - - - -
         1: 
        - 2: 
        - 3: 
        - 4: 
        - 5: 
        - 6: 
        - 7: 
        - 8: 
        - 9: 
        -10: 
        -11: 
        -12: 
        -13: 
        -
        // By using the normal constructor (random1 has type MersenneTwister) 
        -let random1 = MersenneTwister()
        -let random1b = MersenneTwister(42) // with seed
        +
        // By using the normal constructor (random1 has type MersenneTwister) 
        +let random1 = MersenneTwister()
        +let random1b = MersenneTwister(42) // with seed
         
         // By using the Random module (random2 has type System.Random)
        -let random2 = Random.mersenneTwister ()
        -let random2b = Random.mersenneTwisterSeed 42 // with seed
        -let random2c = Random.mersenneTwisterWith 42 false // opt-out of thread-safety
        +let random2 = Random.mersenneTwister ()
        +let random2b = Random.mersenneTwisterSeed 42 // with seed
        +let random2c = Random.mersenneTwisterWith 42 false // opt-out of thread-safety
         
         // Using some other algorithms:
        -let random3 = Random.crypto ()
        -let random4 = Random.xorshift ()
        -let random5 = Random.wh2006 ()
        -
        +let random3 = Random.crypto () +let random4 = Random.xorshift () +let random5 = Random.wh2006 () +

        Shared Instances and Thread Safety

        Generators make certain claims about how many random numbers they can generate until the whole sequence repeats itself. However, this only applies if you @@ -301,43 +297,20 @@ including the SystemRandomSource and CryptoRandomSourceControl.ThreadSafeRandomNumberGenerators (which is used if the constructor argument is omitted).

        For convenience a few generators provide a thread-safe shared instance

        - -
        1: 
        -2: 
        -
        var a = SystemRandomSource.Default;
        +
        var a = SystemRandomSource.Default;
         var b = MersenneTwister.Default;
         

        Or with the F# module:

        - - - -
        1: 
        -2: 
        -3: 
        -4: 
        -5: 
        -
        let a = Random.systemShared
        -let b = Random.mersenneTwisterShared
        +
        let a = Random.systemShared
        +let b = Random.mersenneTwisterShared
         
         // or if you don't care, simply
        -let c = Random.shared;
        -
        +let c = Random.shared; +

        Non-Uniform Random Numbers

        For non-uniform random number generation you can use the wide range of probability distributions in the MathNet.Numerics.Distributions namespace.

        - -
         1: 
        - 2: 
        - 3: 
        - 4: 
        - 5: 
        - 6: 
        - 7: 
        - 8: 
        - 9: 
        -10: 
        -11: 
        -
        using MathNet.Numerics.Distributions;
        +
        using MathNet.Numerics.Distributions;
         
         // sample a single value from a standard distribution
         double a = Normal.Sample(0.0, 1.0);
        @@ -351,109 +324,37 @@ Normal.Samples(c, 0.0, 1.0);
         

        See Probability Distributions for details.

        -
        val samples : obj

        Full name: Random.samples
        -
        val sampleSeq : obj

        Full name: Random.sampleSeq
        -
        val rng : obj

        Full name: Random.rng
        -
        val sample : obj

        Full name: Random.sample
        -
        val sampled : obj

        Full name: Random.sampled
        -
        val someTimeSeed : obj

        Full name: Random.someTimeSeed
        -
        val someGuidSeed : obj

        Full name: Random.someGuidSeed
        -
        val someRobustSeed : obj

        Full name: Random.someRobustSeed
        -
        val samplesSeeded : obj

        Full name: Random.samplesSeeded
        -
        val samplesSeqSeeded : obj

        Full name: Random.samplesSeqSeeded
        -
        val random1 : obj

        Full name: Random.random1
        -
        val random1b : obj

        Full name: Random.random1b
        -
        val random2 : obj

        Full name: Random.random2
        -
        val random2b : obj

        Full name: Random.random2b
        -
        val random2c : obj

        Full name: Random.random2c
        -
        val random3 : obj

        Full name: Random.random3
        -
        val random4 : obj

        Full name: Random.random4
        -
        val random5 : obj

        Full name: Random.random5
        -
        val a : obj

        Full name: Random.a
        -
        val b : obj

        Full name: Random.b
        -
        val c : obj

        Full name: Random.c
        +
        val samples : obj
        +
        val sampleSeq : obj
        +
        val rng : obj
        +
        val sample : obj
        +
        val sampled : obj
        +
        val someTimeSeed : obj
        +
        val someGuidSeed : obj
        +
        val someRobustSeed : obj
        +
        val samplesSeeded : obj
        +
        val samplesSeqSeeded : obj
        +
        val random1 : obj
        +
        val random1b : obj
        +
        val random2 : obj
        +
        val random2b : obj
        +
        val random2c : obj
        +
        val random3 : obj
        +
        val random4 : obj
        +
        val random5 : obj
        +
        val a : obj
        +
        val b : obj
        +
        val c : obj
        - -
        - -
        - - + + + + + + + + + + diff --git a/Regression.html b/Regression.html index 70e6cd02..ebe354ed 100644 --- a/Regression.html +++ b/Regression.html @@ -1,63 +1,138 @@ - - - Curve Fitting: Linear Regression + +<head> + <meta charset="utf-8"> + <title>Curve Fitting: Linear Regression - - - + + + + + + - - - - + - - - - - + + + + + + + + + + + + - - - -
        -
        - -

        Math.NET Numerics

        + + +
        + +
        +
        +

        Curve Fitting: Linear Regression

        Regression is all about fitting a low order parametric model or curve to data, so we can reason about it or make predictions on points not covered by the data. Both data and model are known, but we'd like to find the model parameters that make the model fit best @@ -72,14 +147,7 @@ if you need the data to be reproduced exactly, have a look at interpolation inst \(y : x \mapsto a + b x\) to a set of points \((x_j,y_j)\), where \(x_j\) and \(y_j\) are scalars. Assuming we have two double arrays for x and y, we can use Fit.Line to evaluate the \(a\) and \(b\) parameters of the least squares fit:

        - -
        1: 
        -2: 
        -3: 
        -4: 
        -5: 
        -6: 
        -
        double[] xdata = new double[] { 10, 20, 30 };
        +
        double[] xdata = new double[] { 10, 20, 30 };
         double[] ydata = new double[] { 15, 20, 25 };
         
         Tuple<double, double> p = Fit.Line(xdata, ydata);
        @@ -87,18 +155,12 @@ Tuple<double, double> p double b = p.Item2; // == 0.5; slope
         

        Or in F#:

        - - - -
        1: 
        -
        let a, b = Fit.Line ([|10.0;20.0;30.0|], [|15.0;20.0;25.0|])
        -
        +
        let a, b = Fit.Line ([|10.0;20.0;30.0|], [|15.0;20.0;25.0|])
        +

        How well do these parameters fit the data? The data points happen to be positioned exactly on a line. Indeed, the coefficient of determination confirms the perfect fit:

        - -
        1: 
        -
        GoodnessOfFit.RSquared(xdata.Select(x => a+b*x), ydata); // == 1.0
        +
        GoodnessOfFit.RSquared(xdata.Select(x => a+b*x), ydata); // == 1.0
         

        Linear Model

        In practice, a line is often not an adequate model. But if we can choose a model that is linear, @@ -126,9 +188,7 @@ overdefined system of \(M\) equations:

        Provided the dataset is small enough, if transformed to the normal equation \(\mathbf{X}^T\mathbf y = \mathbf{X}^T\mathbf X \mathbf p\) this can be solved efficiently by the Cholesky decomposition (do not use matrix inversion!).

        - -
        1: 
        -
        Vector<double> p = MultipleRegression.NormalEquations(X, y);
        +
        Vector<double> p = MultipleRegression.NormalEquations(X, y);
         

        Using normal equations is comparably fast as it can dramatically reduce the linear algebra problem to be solved, but that comes at the cost of less precision. If you need more precision, try using @@ -139,9 +199,7 @@ to be solved, but that comes at the cost of less precision. If you need more pre

        The predictor matrix of this model is the Vandermonde matrix. There is a special function in the Fit class for regressions to a polynomial, but note that regression to high order polynomials is numerically problematic.

        - -
        1: 
        -
        double[] p = Fit.Polynomial(xdata, ydata, 3); // polynomial of order 3
        +
        double[] p = Fit.Polynomial(xdata, ydata, 3); // polynomial of order 3
         

        Multiple Regression

        The \(x\) in the linear model can also be a vector \(\mathbf x = [x^{(1)}\; x^{(2)} \cdots x^{(k)}]\) @@ -151,24 +209,14 @@ we end up at the simplest form of ordinary multiple regression:

        \[y : x \mapsto p_0 + p_1 x^{(1)} + p_2 x^{(2)} + \cdots + p_N x^{(N)}\]

        For example, for the data points \((\mathbf{x}_j = [x^{(1)}_j\; x^{(2)}_j], y_j)\) with values ([1,4],15), ([2,5],20) and ([3,2],10) we can evaluate the best fitting parameters with:

        - -
        1: 
        -2: 
        -3: 
        -4: 
        -
        double[] p = Fit.MultiDim(
        +
        double[] p = Fit.MultiDim(
             new[] {new[] { 1.0, 4.0 }, new[] { 2.0, 5.0 }, new[] { 3.0, 2.0 }},
             new[] { 15.0, 20, 10 },
             intercept: true);
         

        The Fit.MultiDim routine uses normal equations, but you can always choose to explicitly use e.g. the QR decomposition for more precision by using the MultipleRegression class directly:

        - -
        1: 
        -2: 
        -3: 
        -4: 
        -
        double[] p = MultipleRegression.QR(
        +
        double[] p = MultipleRegression.QR(
             new[] {new[] { 1.0, 4.0 }, new[] { 2.0, 5.0 }, new[] { 3.0, 2.0 }},
             new[] { 15.0, 20, 10 },
             intercept: true);
        @@ -180,20 +228,11 @@ defined at all the data points. For example, let's have a look at the following
         model in two dimensions:

        \[z : (x, y) \mapsto p_0 + p_1 \mathrm{tanh}(x) + p_2 \psi(x y) + p_3 x^y\]

        Since we map (x,y) to (z) we need to organize the tuples in two arrays:

        - -
        1: 
        -2: 
        -
        double[][] xy = new[] { new[]{x1,y1}, new[]{x2,y2}, new[]{x3,y3}, ...  };
        +
        double[][] xy = new[] { new[]{x1,y1}, new[]{x2,y2}, new[]{x3,y3}, ...  };
         double[] z = new[] { z1, z2, z3, ... };
         

        Then we can call Fit.LinearMultiDim with our model, which will return an array with the best fitting 4 parameters \(p_0, p_1, p_2, p_3\):

        - -
        1: 
        -2: 
        -3: 
        -4: 
        -5: 
        -
        double[] p = Fit.LinearMultiDim(xy, z,
        +
        double[] p = Fit.LinearMultiDim(xy, z,
             d => 1.0,                                  // p0*1.0
             d => Math.Tanh(d[0]),                      // p1*tanh(x)
             d => SpecialFunctions.DiGamma(d[0]*d[1]),  // p2*psi(x*y)
        @@ -203,13 +242,7 @@ model in two dimensions:

        Let's say we have the following model:

        \[y : x \mapsto a + b \ln x\]

        For this case we can use the Fit.LinearCombination function:

        - -
        1: 
        -2: 
        -3: 
        -4: 
        -5: 
        -
        double[] p = Fit.LinearCombination(
        +
        double[] p = Fit.LinearCombination(
             new[] {61.0, 62.0, 63.0, 65.0},
             new[] {3.6,3.8, 4.8, 4.1},
             x => 1.0,
        @@ -219,14 +252,7 @@ model in two dimensions:

        the values of p to the model function, or we can use an alternative function with the Func suffix that returns a function instead of the model parameters. The returned function can then be used to evaluate the parametrized model:

        - -
        1: 
        -2: 
        -3: 
        -4: 
        -5: 
        -6: 
        -
        Func<double,double> f = Fit.LinearCombinationFunc(
        +
        Func<double,double> f = Fit.LinearCombinationFunc(
             new[] {61.0, 62.0, 63.0, 65.0},
             new[] {3.6, 3.8, 4.8, 4.1},
             x => 1.0,
        @@ -239,19 +265,7 @@ For example, the following power function

        \[z : (x, y) \mapsto u x^v y^w\]

        can be transformed into the following linear model with \(\hat{z} = \ln z\) and \(t = \ln u\)

        \[\hat{z} : (x, y) \mapsto t + v \ln x + w \ln y\]

        - -
         1: 
        - 2: 
        - 3: 
        - 4: 
        - 5: 
        - 6: 
        - 7: 
        - 8: 
        - 9: 
        -10: 
        -11: 
        -
        var xy = new[] {new[] { 1.0, 4.0 }, new[] { 2.0, 5.0 }, new[] { 3.0, 2.0 }};
        +
        var xy = new[] {new[] { 1.0, 4.0 }, new[] { 2.0, 5.0 }, new[] { 3.0, 2.0 }};
         var z = new[] { 15.0, 20, 10 };
         
         var z_hat = z.Select(r => Math.Log(r)).ToArray(); // transform z_hat = ln(z)
        @@ -269,106 +283,29 @@ We can achieve this by introducing a weight matrix \(W\)\(\mathbf{X}^T\mathbf{y} = \mathbf{X}^T\mathbf{X}\mathbf{p}\). Such weight matrices
         are often diagonal, with a separate weight for each data point on the diagonal.

        \[\mathbf{X}^T\mathbf{W}\mathbf{y} = \mathbf{X}^T\mathbf{W}\mathbf{X}\mathbf{p}\]

        - -
        1: 
        -
        var p = WeightedRegression.Weighted(X,y,W);
        +
        var p = WeightedRegression.Weighted(X,y,W);
         

        Weighter regression becomes interesting if we can adapt them to the point of interest and e.g. dampen all data points far away. Unfortunately this way the model parameters are dependent on the point of interest \(t\).

        - -
        1: 
        -2: 
        -
        // warning: preliminary api
        +
        // warning: preliminary api
         var p = WeightedRegression.Local(X,y,t,radius,kernel);
         

        Regularization

        Iterative Methods

        -
        val a : obj

        Full name: Regression.a
        -
        val b : obj

        Full name: Regression.b
        +
        val a : obj
        +
        val b : obj
        - -
        - -
        - - + + + + + + + + + + diff --git a/ReleaseNotes-MKL.html b/ReleaseNotes-MKL.html index 59e29a66..b154ab05 100644 --- a/ReleaseNotes-MKL.html +++ b/ReleaseNotes-MKL.html @@ -1,63 +1,138 @@ - - - MKL Provider Release Notes + +<head> + <meta charset="utf-8"> + <title>MKL Provider Release Notes - - - - - - - - - - - - - - - - - - -
        -
        - -

        Math.NET Numerics

        + + + + + + + + + + + + + + + + + + + + + + + + +
        + +
        +
        +

        MKL Provider Release Notes

        Math.NET Numerics | MKL Provider | OpenBLAS Provider

        2.5.0 - 2021-01-01

          @@ -112,88 +187,16 @@
        • Capability querying support
        - -
        -
        - -
        -
        +
        - + + + + + + + +
        + + diff --git a/ReleaseNotes-OpenBLAS.html b/ReleaseNotes-OpenBLAS.html index d1998de9..5851d24f 100644 --- a/ReleaseNotes-OpenBLAS.html +++ b/ReleaseNotes-OpenBLAS.html @@ -1,151 +1,154 @@ - - - OpenBLAS Provider Release Notes + +<head> + <meta charset="utf-8"> + <title>OpenBLAS Provider Release Notes - - - - - - - - - - - - - - - - - - -
        -
        - -

        Math.NET Numerics

        + + + + + + + + + + + + + + + + + + + + + + + + +
        + +
        + -
        - -
        -
        +
        - + + + + + + + +
        + + diff --git a/ReleaseNotes.html b/ReleaseNotes.html index ec60f01f..77526492 100644 --- a/ReleaseNotes.html +++ b/ReleaseNotes.html @@ -1,63 +1,138 @@ - - - Math.NET Numerics Release Notes + +<head> + <meta charset="utf-8"> + <title>Math.NET Numerics Release Notes - - - + + + + + + - - - - + - - - - - + + + + + + + + + + + + - - - -
        -
        - -

        Math.NET Numerics

        + + +
        + +
        +
        +

        Math.NET Numerics Release Notes

        Math.NET Numerics | MKL Provider | OpenBLAS Provider

        5.0.0-alpha02 - 2021-07-11

          @@ -918,88 +993,16 @@ Linear Algebra:
        • Various bug, performance and usability fixes
        - -
        -
        - -
        -
        +
        - + + + + + + + +
        + + diff --git a/Users.html b/Users.html index 27506561..dad5a810 100644 --- a/Users.html +++ b/Users.html @@ -1,63 +1,138 @@ - - - Who is using Math.NET Numerics? + +<head> + <meta charset="utf-8"> + <title>Who is using Math.NET Numerics? - - - + + + + + + - - - - + - - - - - + + + + + + + + + + + + - - - -
        -
        - -

        Math.NET Numerics

        + + +
        + +
        +
        +

        Who is using Math.NET Numerics?

        This page collects anything that references and/or uses Math.NET Numerics. Feel free to add, edit or remove your own work by submitting a pull request.

        Open Source

        @@ -181,88 +256,16 @@ Feel free to - -
        -
        +
        - + + + + + + + +
        + + diff --git a/content/fsdocs-custom.css b/content/fsdocs-custom.css new file mode 100644 index 00000000..c32465db --- /dev/null +++ b/content/fsdocs-custom.css @@ -0,0 +1,5 @@ + +/*-------------------------------------------------------------------------- + Customize your CSS here +/*--------------------------------------------------------------------------*/ + diff --git a/content/fsdocs-default.css b/content/fsdocs-default.css new file mode 100644 index 00000000..965e70b6 --- /dev/null +++ b/content/fsdocs-default.css @@ -0,0 +1,594 @@ +@import url('https://fonts.googleapis.com/css2?family=Hind+Vadodara&family=Roboto+Mono&display=swap'); +/*-------------------------------------------------------------------------- + Formatting for page & standard document content +/*--------------------------------------------------------------------------*/ + +body { + font-family: 'Hind Vadodara', sans-serif; + /* padding-top: 0px; + padding-bottom: 40px; +*/ +} + +/* Format the heading - nicer spacing etc. */ +.masthead { + overflow: hidden; +} + + .masthead .muted a { + text-decoration: none; + color: #999999; + } + + .masthead ul, .masthead li { + margin-bottom: 0px; + } + + .masthead .nav li { + margin-top: 15px; + font-size: 110%; + } + + .masthead h3 { + margin-top: 15px; + margin-bottom: 5px; + font-size: 170%; + } + +/*-------------------------------------------------------------------------- + Formatting fsdocs-content +/*--------------------------------------------------------------------------*/ + +/* Change font sizes for headings etc. */ +#fsdocs-content h1 { + margin: 30px 0px 15px 0px; + /* font-weight: 400; */ + font-size: 2rem; + letter-spacing: 1.78px; + line-height: 2.5rem; + font-weight: 400; +} + +#fsdocs-content h2 { + font-size: 1.6rem; + margin: 20px 0px 10px 0px; + font-weight: 400; +} + +#fsdocs-content h3 { + font-size: 1.2rem; + margin: 15px 0px 10px 0px; + font-weight: 400; +} + +#fsdocs-content hr { + margin: 0px 0px 20px 0px; +} + +#fsdocs-content li { + font-size: 1.0rem; + line-height: 1.375rem; + letter-spacing: 0.01px; + font-weight: 500; + margin: 0px 0px 15px 0px; +} + +#fsdocs-content p { + font-size: 1.0rem; + line-height: 1.375rem; + letter-spacing: 0.01px; + font-weight: 500; + color: #262626; +} + +#fsdocs-content a { + color: #4974D1; +} +/* remove the default bootstrap bold on dt elements */ +#fsdocs-content dt { + font-weight: normal; +} + + + +/*-------------------------------------------------------------------------- + Formatting tables in fsdocs-content, using docs.microsoft.com tables +/*--------------------------------------------------------------------------*/ + +#fsdocs-content .table { + table-layout: auto; + width: 100%; + font-size: 0.875rem; +} + + #fsdocs-content .table caption { + font-size: 0.8rem; + font-weight: 600; + letter-spacing: 2px; + text-transform: uppercase; + padding: 1.125rem; + border-width: 0 0 1px; + border-style: solid; + border-color: #e3e3e3; + text-align: right; + } + + #fsdocs-content .table td, + #fsdocs-content .table th { + display: table-cell; + word-wrap: break-word; + padding: 0.75rem 1rem 0.75rem 0rem; + line-height: 1.5; + vertical-align: top; + border-top: 1px solid #e3e3e3; + border-right: 0; + border-left: 0; + border-bottom: 0; + border-style: solid; + } + + /* suppress the top line on inner lists such as tables of exceptions */ + #fsdocs-content .table .fsdocs-exception-list td, + #fsdocs-content .table .fsdocs-exception-list th { + border-top: 0 + } + + #fsdocs-content .table td p:first-child, + #fsdocs-content .table th p:first-child { + margin-top: 0; + } + + #fsdocs-content .table td.nowrap, + #fsdocs-content .table th.nowrap { + white-space: nowrap; + } + + #fsdocs-content .table td.is-narrow, + #fsdocs-content .table th.is-narrow { + width: 15%; + } + + #fsdocs-content .table th:not([scope='row']) { + border-top: 0; + border-bottom: 1px; + } + + #fsdocs-content .table > caption + thead > tr:first-child > td, + #fsdocs-content .table > colgroup + thead > tr:first-child > td, + #fsdocs-content .table > thead:first-child > tr:first-child > td { + border-top: 0; + } + + #fsdocs-content .table table-striped > tbody > tr:nth-of-type(odd) { + background-color: var(--box-shadow-light); + } + + #fsdocs-content .table.min { + width: unset; + } + + #fsdocs-content .table.is-left-aligned td:first-child, + #fsdocs-content .table.is-left-aligned th:first-child { + padding-left: 0; + } + + #fsdocs-content .table.is-left-aligned td:first-child a, + #fsdocs-content .table.is-left-aligned th:first-child a { + outline-offset: -0.125rem; + } + +@media screen and (max-width: 767px), screen and (min-resolution: 120dpi) and (max-width: 767.9px) { + #fsdocs-content .table.is-stacked-mobile td:nth-child(1) { + display: block; + width: 100%; + padding: 1rem 0; + } + + #fsdocs-content .table.is-stacked-mobile td:not(:nth-child(1)) { + display: block; + border-width: 0; + padding: 0 0 1rem; + } +} + +#fsdocs-content .table.has-inner-borders th, +#fsdocs-content .table.has-inner-borders td { + border-right: 1px solid #e3e3e3; +} + + #fsdocs-content .table.has-inner-borders th:last-child, + #fsdocs-content .table.has-inner-borders td:last-child { + border-right: none; + } + +.fsdocs-entity-list .fsdocs-entity-name { + width: 25%; + font-weight: bold; +} + +.fsdocs-member-list .fsdocs-member-usage { + width: 35%; +} + +/*-------------------------------------------------------------------------- + Formatting xmldoc sections in fsdocs-content +/*--------------------------------------------------------------------------*/ + +.fsdocs-xmldoc, .fsdocs-entity-xmldoc, .fsdocs-member-xmldoc { + font-size: 1.0rem; + line-height: 1.375rem; + letter-spacing: 0.01px; + font-weight: 500; + color: #262626; +} + +.fsdocs-xmldoc h1 { + font-size: 1.2rem; + margin: 10px 0px 0px 0px; +} + +.fsdocs-xmldoc h2 { + font-size: 1.2rem; + margin: 10px 0px 0px 0px; +} + +.fsdocs-xmldoc h3 { + font-size: 1.1rem; + margin: 10px 0px 0px 0px; +} + +/* #fsdocs-nav .searchbox { + margin-top: 30px; + margin-bottom: 30px; +} */ + +#fsdocs-nav img.logo{ + width:90%; + /* height:140px; */ + /* margin:10px 0px 0px 20px; */ + margin-top:40px; + border-style:none; +} + +#fsdocs-nav input{ + /* margin-left: 20px; */ + margin-right: 20px; + margin-top: 20px; + margin-bottom: 20px; + width: 93%; + -webkit-border-radius: 0; + border-radius: 0; +} + +#fsdocs-nav { + /* margin-left: -5px; */ + /* width: 90%; */ + font-size:0.95rem; +} + +#fsdocs-nav li.nav-header{ + /* margin-left: -5px; */ + /* width: 90%; */ + padding-left: 0; + color: #262626; + text-transform: none; + font-size:16px; + margin-top: 9px; + font-weight: bold; +} + +#fsdocs-nav a{ + padding-left: 0; + color: #6c6c6d; + /* margin-left: 5px; */ + /* width: 90%; */ +} + +/*-------------------------------------------------------------------------- + Formatting pre and code sections in fsdocs-content (code highlighting is + further below) +/*--------------------------------------------------------------------------*/ + +#fsdocs-content code { + /* font-size: 0.83rem; */ + font: 0.85rem 'Roboto Mono', monospace; + background-color: #f7f7f900; + border: 0px; + padding: 0px; + /* word-wrap: break-word; */ + /* white-space: pre; */ +} + +/* omitted */ +#fsdocs-content span.omitted { + background: #3c4e52; + border-radius: 5px; + color: #808080; + padding: 0px 0px 1px 0px; +} + +#fsdocs-content pre .fssnip code { + font: 0.86rem 'Roboto Mono', monospace; +} + +#fsdocs-content table.pre, +#fsdocs-content pre.fssnip, +#fsdocs-content pre { + line-height: 13pt; + border: 0px solid #d8d8d8; + border-top: 0px solid #e3e3e3; + border-collapse: separate; + white-space: pre; + font: 0.86rem 'Roboto Mono', monospace; + width: 100%; + margin: 10px 0px 20px 0px; + background-color: #f3f4f7; + padding: 10px; + border-radius: 5px; + color: #8e0e2b; + max-width: none; + box-sizing: border-box; +} + +#fsdocs-content pre.fssnip code { + font: 0.86rem 'Roboto Mono', monospace; + font-weight: 600; +} + +#fsdocs-content table.pre { + background-color: #fff7ed; +} + +#fsdocs-content table.pre pre { + padding: 0px; + margin: 0px; + border-radius: 0px; + width: 100%; + background-color: #fff7ed; + color: #837b79; +} + +#fsdocs-content table.pre td { + padding: 0px; + white-space: normal; + margin: 0px; + width: 100%; +} + +#fsdocs-content table.pre td.lines { + width: 30px; +} + + +#fsdocs-content pre { + word-wrap: inherit; +} + +.fsdocs-example-header { + font-size: 1.0rem; + line-height: 1.375rem; + letter-spacing: 0.01px; + font-weight: 700; + color: #262626; +} + +/*-------------------------------------------------------------------------- + Formatting github source links +/*--------------------------------------------------------------------------*/ + +.fsdocs-source-link { + float: right; + text-decoration: none; +} + + .fsdocs-source-link img { + border-style: none; + margin-left: 10px; + width: auto; + height: 1.4em; + } + + .fsdocs-source-link .hover { + display: none; + } + + .fsdocs-source-link:hover .hover { + display: block; + } + + .fsdocs-source-link .normal { + display: block; + } + + .fsdocs-source-link:hover .normal { + display: none; + } + +/*-------------------------------------------------------------------------- + Formatting logo +/*--------------------------------------------------------------------------*/ + +#fsdocs-logo { + width:140px; + height:140px; + margin:10px 0px 0px 0px; + border-style:none; +} + +/*-------------------------------------------------------------------------- + +/*--------------------------------------------------------------------------*/ + +#fsdocs-content table.pre pre { + padding: 0px; + margin: 0px; + border: none; +} + +/*-------------------------------------------------------------------------- + Remove formatting from links +/*--------------------------------------------------------------------------*/ + +#fsdocs-content h1 a, +#fsdocs-content h1 a:hover, +#fsdocs-content h1 a:focus, +#fsdocs-content h2 a, +#fsdocs-content h2 a:hover, +#fsdocs-content h2 a:focus, +#fsdocs-content h3 a, +#fsdocs-content h3 a:hover, +#fsdocs-content h3 a:focus, +#fsdocs-content h4 a, +#fsdocs-content h4 a:hover, #fsdocs-content +#fsdocs-content h4 a:focus, +#fsdocs-content h5 a, +#fsdocs-content h5 a:hover, +#fsdocs-content h5 a:focus, +#fsdocs-content h6 a, +#fsdocs-content h6 a:hover, +#fsdocs-content h6 a:focus { + color: #262626; + text-decoration: none; + text-decoration-style: none; + /* outline: none */ +} + +/*-------------------------------------------------------------------------- + Formatting for F# code snippets +/*--------------------------------------------------------------------------*/ + +.fsdocs-param-name, +.fsdocs-return-name, +.fsdocs-param { + font-weight: 900; + font-size: 0.85rem; + font-family: 'Roboto Mono', monospace; +} +/* strings --- and stlyes for other string related formats */ +#fsdocs-content span.s { + color: #dd1144; +} +/* printf formatters */ +#fsdocs-content span.pf { + color: #E0C57F; +} +/* escaped chars */ +#fsdocs-content span.e { + color: #EA8675; +} + +/* identifiers --- and styles for more specific identifier types */ +#fsdocs-content span.id { + color: #262626; +} +/* module */ +#fsdocs-content span.m { + color: #009999; +} +/* reference type */ +#fsdocs-content span.rt { + color: #4974D1; +} +/* value type */ +#fsdocs-content span.vt { + color: #43AEC6; +} +/* interface */ +#fsdocs-content span.if { + color: #43AEC6; +} +/* type argument */ +#fsdocs-content span.ta { + color: #43AEC6; +} +/* disposable */ +#fsdocs-content span.d { + color: #43AEC6; +} +/* property */ +#fsdocs-content span.prop { + color: #43AEC6; +} +/* punctuation */ +#fsdocs-content span.p { + color: #43AEC6; +} +#fsdocs-content span.pn { + color: #262626; +} +/* function */ +#fsdocs-content span.f { + color: #e1e1e1; +} +#fsdocs-content span.fn { + color: #990000; +} +/* active pattern */ +#fsdocs-content span.pat { + color: #4ec9b0; +} +/* union case */ +#fsdocs-content span.u { + color: #4ec9b0; +} +/* enumeration */ +#fsdocs-content span.e { + color: #4ec9b0; +} +/* keywords */ +#fsdocs-content span.k { + color: #b68015; + /* font-weight: bold; */ +} +/* comment */ +#fsdocs-content span.c { + color: #808080; + font-weight: 400; + font-style: italic; +} +/* operators */ +#fsdocs-content span.o { + color: #af75c1; +} +/* numbers */ +#fsdocs-content span.n { + color: #009999; +} +/* line number */ +#fsdocs-content span.l { + color: #80b0b0; +} +/* mutable var or ref cell */ +#fsdocs-content span.v { + color: #d1d1d1; + font-weight: bold; +} +/* inactive code */ +#fsdocs-content span.inactive { + color: #808080; +} +/* preprocessor */ +#fsdocs-content span.prep { + color: #af75c1; +} +/* fsi output */ +#fsdocs-content span.fsi { + color: #808080; +} + +/* tool tip */ +div.fsdocs-tip { + background: #475b5f; + border-radius: 4px; + font: 0.85rem 'Roboto Mono', monospace; + padding: 6px 8px 6px 8px; + display: none; + color: #d1d1d1; + pointer-events: none; +} + + div.fsdocs-tip code { + color: #d1d1d1; + font: 0.85rem 'Roboto Mono', monospace; + } + diff --git a/content/fsdocs-search.js b/content/fsdocs-search.js new file mode 100644 index 00000000..3d543cf3 --- /dev/null +++ b/content/fsdocs-search.js @@ -0,0 +1,84 @@ +var lunrIndex, pagesIndex; + +function endsWith(str, suffix) { + return str.indexOf(suffix, str.length - suffix.length) !== -1; +} + +// Initialize lunrjs using our generated index file +function initLunr() { + if (!endsWith(fsdocs_search_baseurl,"/")){ + fsdocs_search_baseurl = fsdocs_search_baseurl+'/' + }; + + // First retrieve the index file + $.getJSON(fsdocs_search_baseurl +"index.json") + .done(function(index) { + pagesIndex = index; + // Set up lunrjs by declaring the fields we use + // Also provide their boost level for the ranking + lunrIndex = lunr(function() { + this.ref("uri"); + this.field('title', { + boost: 15 + }); + this.field('tags', { + boost: 10 + }); + this.field("content", { + boost: 5 + }); + + this.pipeline.remove(lunr.stemmer); + this.searchPipeline.remove(lunr.stemmer); + + // Feed lunr with each file and let lunr actually index them + pagesIndex.forEach(function(page) { + this.add(page); + }, this); + }) + }) + .fail(function(jqxhr, textStatus, error) { + var err = textStatus + ", " + error; + console.error("Error getting Hugo index file:", err); + }); +} + +/** + * Trigger a search in lunr and transform the result + * + * @param {String} query + * @return {Array} results + */ +function search(queryTerm) { + // Find the item in our index corresponding to the lunr one to have more info + return lunrIndex.search(queryTerm+"^100"+" "+queryTerm+"*^10"+" "+"*"+queryTerm+"^10"+" "+queryTerm+"~2^1").map(function(result) { + return pagesIndex.filter(function(page) { + return page.uri === result.ref; + })[0]; + }); +} + +// Let's get started +initLunr(); + +$( document ).ready(function() { + var searchList = new autoComplete({ + /* selector for the search box element */ + minChars: 1, + selector: $("#search-by").get(0), + /* source is the callback to perform the search */ + source: function(term, response) { + response(search(term)); + }, + /* renderItem displays individual search results */ + renderItem: function(item, search) { + search = search.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); + var re = new RegExp("(" + search.split(' ').join('|') + ")", "gi"); + return '
        ' + item.title.replace(re, "$1") + '
        '; + }, + /* onSelect callback fires when a search suggestion is chosen */ + onSelect: function(e, term, item) { + location.href = item.getAttribute('data-uri'); + } + }); +}); diff --git a/content/fsdocs-tips.js b/content/fsdocs-tips.js new file mode 100644 index 00000000..bcd04cb1 --- /dev/null +++ b/content/fsdocs-tips.js @@ -0,0 +1,54 @@ +var currentTip = null; +var currentTipElement = null; + +function hideTip(evt, name, unique) { + var el = document.getElementById(name); + el.style.display = "none"; + currentTip = null; +} + +function findPos(obj) { + // no idea why, but it behaves differently in webbrowser component + if (window.location.search == "?inapp") + return [obj.offsetLeft + 10, obj.offsetTop + 30]; + + var curleft = 0; + var curtop = obj.offsetHeight; + while (obj) { + curleft += obj.offsetLeft; + curtop += obj.offsetTop; + obj = obj.offsetParent; + }; + return [curleft, curtop]; +} + +function hideUsingEsc(e) { + if (!e) { e = event; } + hideTip(e, currentTipElement, currentTip); +} + +function showTip(evt, name, unique, owner) { + document.onkeydown = hideUsingEsc; + if (currentTip == unique) return; + currentTip = unique; + currentTipElement = name; + + var pos = findPos(owner ? owner : (evt.srcElement ? evt.srcElement : evt.target)); + var posx = pos[0]; + var posy = pos[1]; + + var el = document.getElementById(name); + var parent = (document.documentElement == null) ? document.body : document.documentElement; + el.style.position = "absolute"; + el.style.left = posx + "px"; + el.style.top = posy + "px"; + el.style.display = "block"; +} +function Clipboard_CopyTo(value) { + var tempInput = document.createElement("input"); + tempInput.value = value; + document.body.appendChild(tempInput); + tempInput.select(); + document.execCommand("copy"); + document.body.removeChild(tempInput); +} \ No newline at end of file diff --git a/content/img/copy-md-hover.png b/content/img/copy-md-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..b14e94129a15d575b23e6298d364c4272593c1a8 GIT binary patch literal 2886 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 literal 0 HcmV?d00001 diff --git a/content/img/copy-md.png b/content/img/copy-md.png new file mode 100644 index 0000000000000000000000000000000000000000..72de73815f7f422e1f359a1e8c10b5ea5680cbf1 GIT binary patch literal 3351 zcmb_edoo!c$iPrl~c*hp!5a{YEy*|xH4s3q9w!~|{f zfRaE%m45U4$n*U?t|50AX7Z|CyTn(v^UB~!rO^w@b?7)}q?zi6FZgC&MTOgSSQ?&nr+cvig#)-Q@`P)bU5JG`_R_PY0-`AtRcekyUiM^vZ9bi z@`5H58+_Hg!@r)g?~y;Wlz;WmtMT%lt68VIeAU##;omO(viqZ&RsS#QA>_t`raJES zU%REghK;Nz)~kw%e})Wwok<;0IYz*H3LW-~tSnTxsnwY`$K@^#3k+XZoI}mFh{5EV92!rqNNFbRVS#qoC#mJNYr`5?Bgn~x(jC7(hl&IU8TBgu#JI1&9EO)K#lnzuU!e40mI zMj$Xz`Wx!zkd;I3H-sda6CxlQOuIcSfw4dPK(Cn+2ZVadC*TO6Z+sI2nXR1^c(Qrt z*)6hD#Y{~o#U^Lg!X_{gy!<}HYEePa8O?g++Gv%$)338ebMSBLTegrrW8emC2iV*U zg=`N)>c>ir*O>;wP;Wbi|V_;;Wr0Pr7~hXLRpV2Vi=fm5R zsQ%M2o3nB9x<}GATO6EB4*JfHQw0Xsts-NFSAo%^<(vI-}p6agK8XcoLBaC-h?8+z zYTc{9(tQs^)@HO5Rtr3MIc?)wRKE+-O1NVo!NEp7y}jRcATm8ugA?b$n|ak>)`gCn zxAJ|U67I_BD$0ce?|FukIzL&NSC{ogzhfY5VdBzzkE+Jp9V1bIb0wKCSfJME1PJ4~ z9cN!Oej=P#o-nplaBCy|J)2FTP&Cr$iU|*js74ON52a~zR}mL(xLbQFl`9Xh*YC+} zC8IqBth@0{OjFZ!7|Z+m2BO)Y#bhBAN4>Hy z`oZvC&#L|=st$eHRcgzPLMCGnUv$R0YZuPV>Y_&hjW-^kX9_xf#$`4dOuHV2AM;4$ z+(|31o+=aIo)#1oobC0sa8~7b?YQ@x&}D%Dgjs&j=ZB9mVyI@?dMT^5?2;&cWa)hCrUfA>jK|66zgVVww0AucUiP_yKiq=Q{EGfqu0# z($Qy6mP^s3{mQ^AOB1I*^?WF(Z=mUD`o>zVKVh*sfbne!%Ix!^(P znc-Cz{Bhec4_=vEt+i@KTkb*csC{gNAAWUy!&XE@T>uPQp__aP z`=TWIo?o8wf$3=nrl86eyLrXD{qN8M;WZWhpht1u_{RE&y}a{rFOy>m(Y#$b zOlKTrlUAZd&(a~7*k-W3F(RhHrvcB4YR(MmzqlyNi!#iRWN~vA0qir((ueAXac4N0Kbp^j_Hni2C^vox6E0$;l-* zvMIkTrP0U! z{^h#h{S+>jyWBTm)tkXPr^Co12`&FFMYMyI@n}0nMq{cE#Spq9uu%Ze?)XX8gK_^WBn>HSHuyhji62 zA>v(Z%LUsoJyHQpskh~&N!7x$AyaDE*6~mIfPPDu%9XUb!EaxPQE~Om&Ajy&y2%o8 zIx)JUJo0~fuT^=EOW+TaFGIDZ8O2xndAh*$qN7x%0!Y|&y?od0p_1oF+ofu zND!Zpfni(GWP~d-L_jlG-9heF=xiwf6QLYd290zRTvj2I*}GtwD>kl26|Oqg9LM2f zAPih`iK*d#B87lF+&4g^hD#&0!`kyF4{kpPs!c1h7a*^RP-BjM!&^_7Oq5d;^?A>3 zpV_4-?`4n8KpsQZH-cpjNn^Xv%$>1;7d5;?f~*&dmaj?zlxq%L*kk?d`(Muf&F}w% zUP-n@DXH^g4=PFlprOFJxSFIN2tGmw@c`(;f#gXb3<5x`NxF)?5sTdm&cQH`VUOiR zBw?t|ogf~D`7g|MCy0For3CsNeIpK+A)^m~SQ+wE0YCzX2ovi4353%eIGKPkej`CY zhcB$U#@c#Ebu literal 0 HcmV?d00001 diff --git a/content/img/copy-xml-hover.png b/content/img/copy-xml-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..60fea167af78e3854feeae0f86d5b0291c473237 GIT binary patch literal 3192 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 ByA%Kb literal 0 HcmV?d00001 diff --git a/content/img/copy-xml.png b/content/img/copy-xml.png new file mode 100644 index 0000000000000000000000000000000000000000..e5606b907bc27d4e4df733971aa952a118f89a09 GIT binary patch literal 3486 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 literal 806 zcmV+>1KIqEP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGmbN~PnbOGLGA9w%&02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qRNAp5A0007&NklyiRZ_dM+J&{THbRBQ2Kj2Fi3@98KxAP};1Qsq1e#z#5bWXI>-9m9nx-eS z;LglB+?hM`xSRik)nhS zmCyV8bF;H=Ha46NhhuklV|{(jZ1(wl)$3~{K#t_UT3rwOUQwkUZk`IKqA(%lf9*?v0qwene zR;dZU^Lb1hBmT-{IBbo$TCdkjbKAnTx5p?-g#s^De}1#c#Jt$`1kaP~`+!0~W|YN+ z1vu+M0lyz-tjJ5dUD4Bn)qlUeok}JJ)*bM-JkP(~+?2~?Oa*pybcASK2n(SZ9YxLf zfP4*w&?%DfdTmWmps=s3FfucI2FS$Jg@Du3Q_{TeCnq1BPRzGqVgip!q6FWLkHr!& zX;)YD?2JUI5P;7WVpEfo*=#nQPNP$}DUAsbPaLsNZa0mIg#c*bUTA@7W(JmQY?D|B zyXtniXh1-N5P;G~hlfdatg$pyLHs(6CL9h^?=6~z08Ezm;NY3XlFQ|&OTf=``nkmt k3 - - - Math.NET Numerics + +<head> + <meta charset="utf-8"> + <title>Math.NET Numerics - - - + + + + + + - - - - + - - - - - + + + + + + + + + + + + - - - -
        -
        - -

        Math.NET Numerics

        + + +
        + +
        +
        +

        Math.NET Numerics

        Math.NET Numerics aims to provide methods and algorithms for numerical computations in science, engineering and every day use. Covered topics include special functions, linear algebra, probability models, random numbers, interpolation, integration, @@ -83,19 +158,7 @@ that package with the command line tool with nuget.exe install MathNet.Num or simply download the Zip package.

        let's say we have a matrix \(\mathrm{A}\) and want to find an orthonormal basis of the kernel or null-space of that matrix, such that \(\mathrm{A}x = 0\) for all \(x\) in that subspace.

        - -
         1: 
        - 2: 
        - 3: 
        - 4: 
        - 5: 
        - 6: 
        - 7: 
        - 8: 
        - 9: 
        -10: 
        -11: 
        -
        using MathNet.Numerics.LinearAlgebra;
        +
        using MathNet.Numerics.LinearAlgebra;
         using MathNet.Numerics.LinearAlgebra.Double;
         
         Matrix<double> A = DenseMatrix.OfArray(new double[,] {
        @@ -112,57 +175,29 @@ Vector<double>[] nullspace =
         just as well. In order to achieve this we recommend to reference the MathNet.Numerics.FSharp
         package in addition to MathNet.Numerics, which adds a few modules to make it more
         idiomatic and includes arbitrary precision types (BigInteger, BigRational).

        - - - -
        1: 
        -2: 
        -3: 
        -4: 
        -
        open MathNet.Numerics.LinearAlgebra
        -let m = matrix [[ 1.0; 2.0 ]
        -                [ 3.0; 4.0 ]]
        -let m' = m.Inverse()
        -
        +
        open MathNet.Numerics.LinearAlgebra
        +let m = matrix [[ 1.0; 2.0 ]
        +                [ 3.0; 4.0 ]]
        +let m' = m.Inverse()
        +

        It also works well in the interactive F# environment (REPL) which can be launched with fsharpi on all platforms (including Linux). As a start let's enter the following lines into F# interactive. Append ;; to the end of a line to run all code up to there immediately and print the result to the output. Use the tab key for auto-completion or #help;; for help. For convenience our F# packages include a small script that sets everything up properly:

        - - - -
        1: 
        -2: 
        -3: 
        -4: 
        -5: 
        -6: 
        -7: 
        -8: 
        -
        #load "../packages/MathNet.Numerics.FSharp/MathNet.Numerics.fsx"
        +
        #load "../packages/MathNet.Numerics.FSharp/MathNet.Numerics.fsx"
         
        -open MathNet.Numerics
        -SpecialFunctions.Gamma(0.5)
        +open MathNet.Numerics
        +SpecialFunctions.Gamma(0.5)
         
        -open MathNet.Numerics.LinearAlgebra
        -let m : Matrix<float> = DenseMatrix.randomStandard 50 50
        -(m * m.Transpose()).Determinant()
        -
        +open MathNet.Numerics.LinearAlgebra +let m : Matrix<float> = DenseMatrix.randomStandard 50 50 +(m * m.Transpose()).Determinant() +

        Visual Basic

        Let's use Visual Basic to find the polynomial roots \(x\) such that \(2x^2 - 2x - 2 = 0\) numerically. We already know there are two roots, one between -2 and 0, the other between 0 and 2:

        - -
        1: 
        -2: 
        -3: 
        -4: 
        -5: 
        -6: 
        -7: 
        -8: 
        -9: 
        -
        Imports MathNet.Numerics.RootFinding
        +
        Imports MathNet.Numerics.RootFinding
         
         Dim f As Func(Of Double, Double) = Function(x) 2*x^2 - 2*x - 2
         
        @@ -176,54 +211,24 @@ FindRoots.Quadratic(-2, -2, 2)
         

        You need a recent version of Mono in order to use Math.NET Numerics on anything other than Windows. Luckily there has been great progress lately to make both Mono and F# available as proper Debian packages. In Debian testing and Ubuntu 14.04 (trusty/universe) you can install both of them with APT:

        - -
        1: 
        -2: 
        -3: 
        -
        sudo apt-get update
        +
        sudo apt-get update
         sudo apt-get install mono-complete
         sudo apt-get install fsharp
         

        If you don't have NuGet yet:

        - -
        1: 
        -2: 
        -
        sudo mozroots --import --sync
        +
        sudo mozroots --import --sync
         curl -L https://nuget.org/nuget.exe -o nuget.exe
         

        Then you can use NuGet to fetch the latest binaries in your working directory. The -Pre argument causes it to include pre-releases, omit it if you want stable releases only.

        - -
        1: 
        -2: 
        -3: 
        -
        mono nuget.exe install MathNet.Numerics -Pre -OutputDirectory packages
        +
        mono nuget.exe install MathNet.Numerics -Pre -OutputDirectory packages
         # or if you intend to use F#:
         mono nuget.exe install MathNet.Numerics.FSharp -Pre -OutputDirectory packages
         

        In practice you'd probably use the Monodevelop IDE instead which can take care of fetching and updating NuGet packages and maintain assembly references. But for completeness let's use the compiler directly this time. Let's create a C# file Start.cs:

        - -
         1: 
        - 2: 
        - 3: 
        - 4: 
        - 5: 
        - 6: 
        - 7: 
        - 8: 
        - 9: 
        -10: 
        -11: 
        -12: 
        -13: 
        -14: 
        -15: 
        -16: 
        -17: 
        -18: 
        -
        using System;
        +
        using System;
         using MathNet.Numerics;
         using MathNet.Numerics.LinearAlgebra;
         
        @@ -243,31 +248,14 @@ Let's create a C# file Start.cs:

        }

        Compile and run:

        - -
        1: 
        -2: 
        -3: 
        -4: 
        -5: 
        -
        # single line:
        +
        # single line:
         mcs -optimize -lib:packages/MathNet.Numerics.3.0.0-alpha8/lib/net40/
                       -r:MathNet.Numerics.dll Start.cs -out:Start
         # launch:
         mono Start
         

        Which will print something like the following to the output:

        - -
         1: 
        - 2: 
        - 3: 
        - 4: 
        - 5: 
        - 6: 
        - 7: 
        - 8: 
        - 9: 
        -10: 
        -
        0.520499877813047
        +
        0.520499877813047
         DenseVector 500-Double
            -0.181414     -1.25024    -0.607136      1.12975     -3.31201     0.344146
             0.934095     -2.96364      1.84499      1.20752     0.753055      1.56942
        @@ -280,91 +268,27 @@ DenseVector 500-Double
         

        See Intel MKL for details how to use native providers on Linux.

        -
        val m : obj

        Full name: index.m
        -
        val m' : obj

        Full name: index.m'
        -
        Multiple items
        val float : value:'T -> float (requires member op_Explicit)

        Full name: Microsoft.FSharp.Core.Operators.float

        --------------------
        type float = System.Double

        Full name: Microsoft.FSharp.Core.float

        --------------------
        type float<'Measure> = float

        Full name: Microsoft.FSharp.Core.float<_>
        +
        val m : obj
        +
        val m' : obj
        +
        Multiple items
        val float : value:'T -> float (requires member op_Explicit)
        <summary>Converts the argument to 64-bit float. This is a direct conversion for all + primitive numeric types. For strings, the input is converted using <c>Double.Parse()</c> + with InvariantCulture settings. Otherwise the operation requires an appropriate + static conversion method on the input type.</summary>
        <param name="value">The input value.</param>
        <returns>The converted float</returns>


        --------------------
        [<Struct>] +type float = System.Double
        <summary>An abbreviation for the CLI type <see cref="T:System.Double" />.</summary>
        <category>Basic Types</category>


        --------------------
        type float<'Measure> = + float
        <summary>The type of double-precision floating point numbers, annotated with a unit of measure. + The unit of measure is erased in compiled code and when values of this type + are analyzed using reflection. The type is representationally equivalent to + <see cref="T:System.Double" />.</summary>
        <category index="6">Basic Types with Units of Measure</category>
        - -
        - -
        - - + + + + + + + + + + diff --git a/index.json b/index.json new file mode 100644 index 00000000..f5c4efcc --- /dev/null +++ b/index.json @@ -0,0 +1 @@ +[{"uri":"https://numerics.mathdotnet.com/Build.html","title":"Building Math.NET Numerics\r\n","content":"Building Math.NET Numerics\r\n==========================\r\n\r\nIf you do not want to use the official binaries, or if you like to modify,\r\ndebug or contribute, you can compile locally either using Visual Studio or\r\nmanually with the build scripts.\r\n\r\nSystem Requirements\r\n-------------------\r\n\r\n* .NET Core SDK 3.1.1 ([download](https://dotnet.microsoft.com/download/dotnet-core/3.1))\r\n\r\nVisualStudio and other IDEs\r\n---------------------------\r\n\r\nWe clearly separate dependency management from the IDE and therefore recommend to\r\nrun \u0060restore.cmd\u0060 or \u0060restore.sh\u0060 once after every git checkout in order to restore\r\nthe dependencies exactly as defined. Otherwise Visual Studio and other IDEs\r\nmay fail to compile or provide correct IntelliSense.\r\n\r\nTests can be run with the usual integrated NUnit test runners or ReSharper.\r\n\r\nCommand Line Tools\r\n------------------\r\n\r\nInstead of a compatible IDE you can also build the solutions directly with\r\nthe .NET Core SDK build tools. You may need to run \u0060restore.cmd\u0060 or \u0060restore.sh\u0060\r\nbefore, once after every git checkout in order to restore the dependencies.\r\n\r\n restore.cmd (or ./restore.sh)\r\n dotnet build MathNet.Numerics.sln\r\n\r\nFAKE\r\n----\r\n\r\nThe fully automated build including unit tests, documentation and api\r\nreference, NuGet and Zip packages is using [FAKE](https://fsharp.github.io/FAKE/).\r\n\r\nFAKE itself is not included in the repository but it will download and bootstrap\r\nitself automatically when build.cmd is run the first time. Note that this step\r\nis *not* required when using Visual Studio or the .NET Core SDK directly.\r\n\r\n ./build.sh # normal build and unit tests, when using bash shell on Windows or Linux.\r\n build.cmd # normal build and unit tests, when using Windows CMD shell.\r\n\r\n ./build.sh build # normal build\r\n ./build.sh build strongname # normal build and also build strong-named variant\r\n\r\n ./build.sh test # normal build, run unit tests\r\n ./build.sh test quick # normal build, run unit tests except long running ones\r\n\r\n ./build.sh clean # cleanup build artifacts\r\n ./build.sh docs # generate documentation\r\n ./build.sh api # generate api reference\r\n\r\n ./build.sh all # build, test, docs, api reference\r\n\r\nIf the build or tests fail claiming that FSharp.Core was not be found, see\r\n[fsharp.org](https://fsharp.org/use/windows/) or install the\r\n[Visual F# 3.0 Tools](https://go.microsoft.com/fwlink/?LinkId=261286) directly.\r\n\r\nDependencies\r\n------------\r\n\r\nWe manage NuGet and other dependencies with [Paket](https://fsprojects.github.io/Paket/).\r\nYou do not normally have to do anything with Paket as it is integrated into our\r\nFAKE build tools, unless you want to actively manage the dependencies.\r\n\r\n\u0060.paket/paket.exe restore\u0060 will restore the packages\r\nto the exact version specified in the \u0060paket.lock\u0060 file,\r\n\u0060.paket/paket.exe install\u0060 will install or migrate packages after you have\r\nmade changes to the \u0060paket.dependencies\u0060 file, \u0060.paket/paket.exe outdated\u0060\r\nwill show whether any packages are out of date and \u0060.paket/paket.exe update\u0060\r\nwill update all packages within the defined constraints. Have a look at the Paket\r\nwebsite for more commands and details.\r\n\r\nDocumentation\r\n-------------\r\n\r\nThis website and documentation is automatically generated from of a set of\r\n[CommonMark](https://commonmark.org/) structured files in \u0060doc/content/\u0060 using\r\n[FSharp.Formatting](https://tpetricek.github.io/FSharp.Formatting/).\r\nThe final documentation can be built by calling \u0060build.sh docs\u0060.\r\n\r\nHowever, for editing and previewing the docs on your local machine it is more\r\nconvenient to run \u0060build.sh DocsWatch\u0060 in a separate console instead, which\r\nmonitors the content files and incrementally regenerates the HTML output\r\nautomatically. DocsWatch will also use local/relative URIs instead of absolute\r\nones, so that the links and styles will work as expected locally. This can\r\nalso be enabled in a full one-time build with \u0060build.sh DocsDev\u0060 instead\r\nof just \u0060Docs\u0060.\r\n\r\nCreating a Release\r\n------------------\r\n\r\nWhile only maintainers can make official releases published on NuGet and\r\nreferred to from the website, you can use the same tools to make your own\r\nreleases for your own purposes.\r\n\r\nVersioning is controlled by the release notes. Before building a new version,\r\nfirst add a new release header and change notes on top of the \u0060RELEASENOTES.md\u0060\r\ndocument in the root directory. The fake builds pick this up and propagate it\r\nto the assembly info files automatically.\r\n\r\nThe build can then be launched by calling:\r\n\r\n ./build.sh all\r\n\r\nThe build script will print the current version as part of the the header banner,\r\nwhich is also included in the release notes document in the build artifacts.\r\nExample:\r\n\r\n // __ __ _ _ _ _ ______ _______\r\n // | \\/ | | | | | | \\ | | ____|__ __|\r\n // | \\ / | __ _| |_| |__ | \\| | |__ | |\r\n // | |\\/| |/ _\u0060 | __| \u0027_ \\ | . \u0060 | __| | |\r\n // | | | | (_| | |_| | | |_| |\\ | |____ | |\r\n // |_| |_|\\__,_|\\__|_| |_(_)_| \\_|______| |_|\r\n //\r\n // Math.NET Numerics - https://numerics.mathdotnet.com\r\n // Copyright (c) Math.NET - Open Source MIT/X11 License\r\n //\r\n // Math.NET Numerics v3.5.0\r\n // Math.NET Numerics MKL Provider v1.7.0\r\n // Math.NET Numerics Data Extensions v3.1.0\r\n\r\nThe artifacts are then ready in the \u0060out/packages\u0060 directory.\r\n\r\nExtra Packages\r\n--------------\r\n\r\nIn addition to the core package this repository also include extra packages\r\nlike the data extensions. Most build targets are available for\r\nthese packages as well, with the following prefixes:\r\n\r\n* \u0060Data\u0060 for the Data Extensions\r\n\r\nExample: \u0060build.sh DataBuild\u0060\r\n\r\nIntel MKL on Windows\r\n--------------------\r\n\r\nBuilding the Intel MKL native provider for Windows requires additionally:\r\n\r\n* Either Intel Parallel Studio 2020 or Intel Math Kernel Library 2020 is installed\r\n* Visual Studio 2019, with the following options\r\n * Desktop development with C\u002B\u002B workload\r\n * Windows 10 SDK (10.0.17763.0)\r\n * MSVC v142 - VS 2019 C\u002B\u002B x64/x86 build tools\r\n\r\nThe build can then be triggered by calling:\r\n\r\n ./build.sh MklWinBuild // build both 32 and 64 bit variants\r\n ./build.sh MklTest // run all tests with the MKL provider enforced\r\n ./build.sh MklWinAll // build and run tests\r\n\r\nIf you run into an error with \u0060mkl_link_tool.exe\u0060 you may need to patch a targets file,\r\nsee [MKL 2020.1, VS2019 linking bug ](https://software.intel.com/en-us/forums/intel-math-kernel-library/topic/851578).\r\n\r\nThe build puts the binaries to \u0060out/MKL/Windows/x64\u0060 (and \u0060x86\u0060), the NuGet package\r\nto \u0060out/MKL/NuGet\u0060 and a Zip archive to \u0060out/MKL/Zip\u0060. You can directly use the provider from\r\nthere by setting \u0060Control.NativeProviderPath\u0060 to the full path pointing to \u0060out/MKL/Windows/\u0060;\r\nthis is also what the unit tests do when you run the \u0060MklTest\u0060 build target.\r\n\r\nOfficial Release Process (Maintainers only)\r\n-------------------------------------------\r\n\r\n* Update \u0060RELEASENOTES.md\u0060 file with relevant changes, attributed by contributor (if external). Set date.\r\n* Update \u0060CONTRIBUTORS.md\u0060 file (via \u0060git shortlog -sn\u0060)\r\n\r\n* Build Release:\r\n\r\n build.sh all strongname\r\n\r\n* Commit and push release notes and (auto-updated) assembly info files with new \u0022Release: v1.2.3\u0022 commit\r\n\r\n* Publish Release:\r\n\r\n build.sh PublishDocs\r\n build.sh PublishApi\r\n build.sh PublishTag\r\n build.sh PublishArchive\r\n build.sh PublishNuGet\r\n\r\n* Consider a tweet via [@MathDotNet](https://twitter.com/MathDotNet)\r\n* Update Wikipedia release version and date for the\r\n [Math.NET Numerics](https://en.wikipedia.org/wiki/Math.NET_Numerics) and\r\n [Comparison of numerical analysis software](https://en.wikipedia.org/wiki/Comparison_of_numerical_analysis_software) articles.\r\n"},{"uri":"https://numerics.mathdotnet.com/Compatibility.html","title":"Platform Support\r\n","content":"Platform Support\r\n================\r\n\r\nSupported Platforms:\r\n\r\n- .NET 5.0 or higher, with builds for 5.0.\r\n- .NET Framework 4.6.1 or higher, with builds for 4.6.1 and 4.8.\r\n- .NET Standard 2.0 or higher, with builds for 2.0.\r\n- Mono (via .NET Standard)\r\n- Windows, Linux and Mac.\r\n\r\n\r\nDependencies\r\n------------\r\n\r\nPackage Dependencies:\r\n\r\n- .NET 5.0 and higher: None\r\n- .NET Framework 4.6.1: [System.ValueTuple](https://www.nuget.org/packages/System.ValueTuple)\r\n- .NET Framework 4.8 and higher: None\r\n- .Net Standard 2.0 and higher: None\r\n- F#: additionally [FSharp.Core](https://www.nuget.org/packages/FSharp.Core)\r\n"},{"uri":"https://numerics.mathdotnet.com/Constants.html","title":"Constants\r\n","content":"Constants\r\n=========\r\n\r\nMath.NET Numerics contains a set of often used mathematical and scientific\r\nconstants. Mathematical and defined scientific constants are as accurate as\r\ndouble precision allows, while measured constants are implemented according\r\nto 2007 CODATA.\r\n\r\nAll constants are defined as static constant fields of the \u0060Constants\u0060 class.\r\n\r\n\r\nSI Unit Scaling\r\n---------------\r\n\r\nConstant | Factor | Constant | Factor\r\n-------- | --------- | -------- | ----------\r\nDeca | $10^{1}$ | Deci | $10^{-1}$\r\nHecto | $10^{2}$ | Centi | $10^{-2}$\r\nKilo | $10^{3}$ | Milli | $10^{-3}$\r\nMega | $10^{6}$ | Micro | $10^{-6}$\r\nGiga | $10^{9}$ | Nano | $10^{-9}$\r\nTera | $10^{12}$ | Pico | $10^{-12}$\r\nPeta | $10^{15}$ | Femto | $10^{-15}$\r\nExa | $10^{18}$ | Atto | $10^{-18}$\r\nZetta | $10^{21}$ | Zepto | $10^{-21}$\r\nYotta | $10^{24}$ | Yocto | $10^{-24}$\r\n\r\n\r\nMathematical Constants\r\n----------------------\r\n\r\nConstant | Definition | Value (Rounded)\r\n----------------- | ------------------------- | ---------------\r\nE | $e$ | 2.7182818284590452354\r\nLog2E | $\\log_2{e}$ | 1.4426950408889634074\r\nLog10E | $\\log_{10}{e}$ | 0.4342944819032518277\r\nLn2 | $\\log_e{2}$ | 0.6931471805599453094\r\nLn10 | $\\log_e{10}$ | 2.3025850929940456840\r\nLnPi | $\\log_e{\\pi}$ | 1.1447298858494001741\r\nLn2PiOver2 | $\\frac{1}{2}\\log_e{2\\pi}$ | 0.9189385332046727418\r\nInvE | $\\frac{1}{e}$ | 0.3678794411714423216\r\nSqrtE | $\\sqrt{e}$ | 1.6487212707001281468\r\nSqrt2 | $\\sqrt{2}$ | 1.4142135623730950488\r\nSqrt3 | $\\sqrt{3}$ | 1.7320508075688772935\r\nSqrt1Over2 | $\\sqrt{\\frac{1}{2}} = \\frac{1}{\\sqrt{2}} = \\frac{\\sqrt{2}}{2}$ | 0.7071067811865475244\r\nHalfSqrt3 | $\\frac{1}{2}\\sqrt{3}$ | 0.8660254037844386468\r\nPi | $\\pi$ | 3.1415926535897932385\r\nPi2 | $2\\pi$ | 6.2831853071795864769\r\nPiOver2 | $\\frac{1}{2}\\pi$ | 1.5707963267948966192\r\nPi3Over2 | $\\frac{3}{2}\\pi$ | 4.7123889803846898577\r\nPiOver4 | $\\frac{1}{4}\\pi$ | 0.7853981633974483096\r\nSqrtPi | $\\sqrt{\\pi}$ | 1.7724538509055160273\r\nSqrt2Pi | $\\sqrt{2\\pi}$ | 2.5066282746310005024\r\nSqrt2PiE | $\\sqrt{2\\pi e}$ | 4.1327313541224929385\r\nLogSqrt2Pi | $\\log_e{\\sqrt{2\\pi}} = \\frac{1}{2}\\log_e{2\\pi}$ | 0.9189385332046727418\r\nLogSqrt2PiE | $\\log_e{\\sqrt{2\\pi e}}$ | 1.4189385332046727418\r\nLogTwoSqrtEOverPi | $\\log_e{2\\sqrt{\\frac{e}{\\pi}}}$ | 0.6207822376352452223\r\nInvPi | $\\frac{1}{\\pi}$ | 0.3183098861837906715\r\nTwoInvPi | $\\frac{2}{\\pi}$ | 0.6366197723675813431\r\nInvSqrtPi | $\\frac{1}{\\sqrt{\\pi}}$ | 0.5641895835477562869\r\nInvSqrt2Pi | $\\frac{1}{\\sqrt{2\\pi}}$ | 0.3989422804014326779\r\nTwoInvSqrtPi | $\\frac{2}{\\sqrt{2\\pi}}$ | 1.1283791670955125739\r\nTwoSqrtEOverPi | $2\\sqrt{\\frac{e}{\\pi}}$ | 1.8603827342052657173\r\nCatalan | $\\beta(2) = \\sum_{k=0}^{\\infty}{\\frac{(-1)^k}{(2k\u002B1)^2}}$ | 0.9159655941772190151\r\nEulerMascheroni | $\\gamma = \\lim_{n\\to\\infty} {\\sum_{k=1}^n{(\\frac{1}{k} - \\log_e{n})}}$ | 0.5772156649015328606\r\nGoldenRatio | $\\frac{1\u002B\\sqrt{5}}{2}$ | 1.6180339887498948482\r\nGlaisher | $\\exp{(\\frac{1}{12} - \\zeta{(-1)})}$ | 1.2824271291006226369\r\nKhinchin | $K_0 = \\prod_{k=1}^{\\infty}{(1\u002B\\frac{1}{k(k\u002B2)})^{\\log_2{k}}}$ | 2.6854520010653064453\r\n\r\n\r\nUniversal Constants\r\n-------------------\r\n\r\nConstant | Symbol | Unit | Value\r\n----------------------------- | ------- | ------------- | -----\r\nSpeedOfLight | $c_0$ | $\\frac{m}{s}$ | 2.99792458e\u002B8\r\nMagneticPermeability | $\\mu_0$ | $\\frac{N}{A^2}$ = $\\frac{kg\\,m}{A^2s^2}$ | 1.2566370614359172954e-6\r\nElectricPermittivity | $\\varepsilon_0$ | $\\frac{F}{m}$ = $\\frac{A^2s^4}{kg\\,m^3}$ | 8.8541878171937079245e-12\r\nCharacteristicImpedanceVacuum | $Z_0$ | $\\Omega = \\frac{kg\\,m^2}{A^2s^3}$ | 376.7303134617706554682\r\nGravitationalConstant | $G$ | $\\frac{m^3}{kg\\,s^2}$ | 6.67429e-11\r\nPlancksConstant | $h$ | $J\\,s = \\frac{kg\\,m^2}{s}$ | 6.62606896e-34\r\nDiracsConstant | $\\hbar$ | $J\\,s = \\frac{kg\\,m^2}{s}$ | 1.054571629e-34\r\nPlancksMass | $m_p$ | $kg$ | 2.17644e-8\r\nPlancksTemperature | $T_p$ | $K$ | 1.416786e\u002B32\r\nPlancksLength | $l_p$ | $m$ | 1.616253e-35\r\nPlancksTime | $t_p$ | $s$ | 5.39124e-44\r\n\r\n\r\nElectromagnetic Constants\r\n-------------------------\r\n\r\nConstant | Symbol | Unit | Value\r\n------------------- | ---------- | --------------------------------- | -----\r\nElementaryCharge | $e$ | $C = A\\,s$ | 1.602176487e-19\r\nMagneticFluxQuantum | $\\Theta_0$ | $Wb = \\frac{kg\\,m^2}{A\\,s^2}$ | 2.067833668e-15\r\nConductanceQuantum | $G_0$ | $S = \\frac{A^2s^3}{kg\\,m^2}$ | 7.7480917005e-5\r\nJosephsonConstant | $K_J$ | $\\frac{Hz}{V}$ | 483597.891e\u002B9\r\nVonKlitzingConstant | $R_K$ | $\\Omega = \\frac{kg\\,m^2}{A^2s^3}$ | 25812.807557\r\nBohrMagneton | $\\mu_B$ | $\\frac{J}{T}$ | 927.400915e-26\r\nNuclearMagneton | $\\mu_N$ | $\\frac{J}{T}$ | 5.05078324e-27\r\n\r\n\r\nAtomic and Nuclear Constants\r\n----------------------------\r\n\r\nConstant | Symbol | Unit | Value\r\n--------------------- | ------------ | ----------------- | -----\r\nFineStructureConstant | $\\alpha$ | $1$ | 7.2973525376e-3\r\nRydbergConstant | $T_{\\infty}$ | $\\frac{1}{m}$ | 10973731.568528\r\nBohrRadius | $a_0$ | $m$ | 0.52917720859e-10\r\nHartreeEnergy | $E_h$ | $J$ | 4.35974394e-18\r\nQuantumOfCirculation | | $\\frac{m^2}{s}$ | 3.6369475199e-4\r\nFermiCouplingConstant | | $\\frac{1}{GeV^2}$ | 1.16637e-5\r\nWeakMixingAngle | | | 0.22256\r\nAvogadro | | $\\frac{1}{mol}$ | 6.0221412927e23\r\n\r\n#### Electron\r\n\r\nConstant | Unit | Value\r\n---------------------------- | ---------------- | -----\r\nElectronMass | $kg$ | 9.10938215e-31\r\nElectronMassEnergyEquivalent | $J$ | 8.18710438e-14\r\nElectronMolarMass | $\\frac{kg}{mol}$ | 5.4857990943e-7\r\nComptonWavelength | $m$ | 2.4263102175e-12\r\nClassicalElectronRadius | $m$ | 2.8179402894e-15\r\nThomsonCrossSection | $m^2$ | 0.6652458558e-28\r\nElectronMagneticMoment | $\\frac{J}{T}$ | -928.476377e-26\r\nElectronGFactor | | -2.0023193043622\r\n\r\n#### Muon\r\n\r\nConstant | Unit | Value\r\n------------------------ | ---------------- | -----\r\nMuonMass | $kg$ | 1.88353130e-28\r\nMuonMassEnegryEquivalent | $J$ | 1.692833511e-11\r\nMuonMolarMass | $\\frac{kg}{mol}$ | 0.1134289256e-3\r\nMuonComptonWavelength | $m$ | 11.73444104e-15\r\nMuonMagneticMoment | $\\frac{J}{T}$ | -4.49044786e-26\r\nMuonGFactor | | -2.0023318414\r\n\r\n#### Tau\r\n\r\nConstant | Unit | Value\r\n----------------------- | ---------------- | -----\r\nTauMass | $kg$ | 3.16777e-27\r\nTauMassEnergyEquivalent | $J$ | 2.84705e-10\r\nTauMolarMass | $\\frac{kg}{mol}$ | 1.90768e-3\r\nTauComptonWavelength | $m$ | 0.69772e-15\r\n\r\n#### Proton\r\n\r\nConstant | Unit | Value\r\n------------------------------- | ---------------- | -----\r\nProtonMass | $kg$ | 1.672621637e-27\r\nProtonMassEnergyEquivalent | $J$ | 1.503277359e-10\r\nProtonMolarMass | $\\frac{kg}{mol}$ | 1.00727646677e-3\r\nProtonComptonWavelength | $m$ | 1.3214098446e-15\r\nProtonMagneticMoment | $\\frac{J}{T}$ | 1.410606662e-26\r\nShieldedProtonMagneticMoment | $\\frac{J}{T}$ | 1.410570419e-26\r\nProtonGFactor | | 5.585694713\r\nProtonGyromagneticRatio | $\\frac{1}{T\\,s}$ | 2.675222099e8\r\nShieldedProtonGyromagneticRatio | $\\frac{1}{T\\,s}$ | 2.675153362e8\r\n\r\n#### Neutron\r\n\r\nConstant | Unit | Value\r\n--------------------------- | ---------------- | -----\r\nNeutronMass | $kg$ | 1.674927212e-27\r\nNeutronMassEnegryEquivalent | $J$ | 1.505349506e-10\r\nNeutronMolarMass | $\\frac{kg}{mol}$ | 1.00866491597e-3\r\nNeutronComptonWavelength | $m$ | 1.3195908951e-1\r\nNeutronMagneticMoment | $\\frac{J}{T}$ | -0.96623641e-26\r\nNeutronGFactor | | -3.82608545\r\nNeutronGyromagneticRatio | $\\frac{1}{T\\,s}$ | 1.83247185e8\r\n\r\n#### Deuteron\r\n\r\nConstant | Unit | Value\r\n---------------------------- | ---------------- | -----\r\nDeuteronMass | $kg$ | 3.34358320e-27\r\nDeuteronMassEnegryEquivalent | $J$ | 3.00506272e-10\r\nDeuteronMolarMass | $\\frac{kg}{mol}$ | 2.013553212725e-3\r\nDeuteronMagneticMoment | $\\frac{J}{T}$ | 0.433073465e-26\r\n\r\n#### Helion\r\n\r\nConstant | Unit | Value\r\n-------------------------- | ---------------- | -----\r\nHelionMass | $kg$ | 5.00641192e-27\r\nHelionMassEnegryEquivalent | $J$ | 4.49953864e-10\r\nHelionMolarMass | $\\frac{kg}{mol}$ | 3.0149322473e-3\r\n"},{"uri":"https://numerics.mathdotnet.com/Contributing.html","title":"Contribute to Math.NET Numerics\r\n","content":"Contribute to Math.NET Numerics\r\n===============================\r\n\r\nMath.NET Numerics is driven by the community and contributors like you. I\u0027m excited that you\u0027re interested to help us move forward and improve Numerics. We usually accept contributions and try to attribute them properly, provided they keep the library consistent, focused and mathematically accurate. Have a look at the following tips to get started quickly. I\u0027m looking forward to your pull requests! Thanks!\r\n\r\n\u2014 *Christoph R\u00FCegg (@cdrnet)*\r\n\r\n## Getting Started\r\n\r\n- Make sure you have a [GitHub account](https://github.com/signup/free), it\u0027s free.\r\n- Please configure a proper name and email address in git ([how to](https://help.github.com/articles/set-up-git)). Real names are preferred, but it is acceptable to use an alias or even an obviously fake email address if you wish not to be contacted, as long as something is explicitly configured (not the default).\r\n- Fork the [mainline repository](https://github.com/mathnet/mathnet-numerics) on GitHub ([how to](https://help.github.com/articles/fork-a-repo)).\r\n\r\nWe use the [Fork \u0026 Pull Model](https://help.github.com/articles/using-pull-requests/), as common for GitHub projects. If you\u0027ve already contributed to another GitHub project then you\u0027re all set. If not, [here is another introduction](https://gun.io/blog/how-to-github-fork-branch-and-pull-request/).\r\n\r\n**C# Solutions, Projects and Files** \r\nWe have two kind of C# projects: primary (*Numerics.csproj, UnitTests.csproj*) and secondary (*Numerics-xy.csproj, UnitTests-xy.csproj*). The primary ones are the common VisualStudio project files you usually work with. The secondary projects on the other hand are not intended to be modified and include all files automatically. Whenever you need to add, remove or move a file, please do so in the primary projects only. In most cases we recommend to work with the \u0060MathNet.Numerics.sln\u0060 solution which only includes primary projects anyway - except when working on and testing portability/compatibility.\r\n\r\n**F# Projects** \r\nF# does not support the wildcard approach of the C# projects by design, so whenever you add, remove or move an F# file please manually update all F# projects accordingly, including the secondary platform specific ones in the \u0060MathNet.Numerics.All.sln\u0060 solution. This is a bit tedious but we have not found a better solution yet.\r\n\r\n**Separate Branch per Pull Request** \r\nWe recommend that you create a separate branch for each pull request, as opposed to using master. This makes it much easier to continue working on a pull request even after it has been opened on GitHub. Remember that GitHub automatically includes all future commits of the same branch to the pull request.\r\n\r\n**Focused** \r\nWe prefer a couple small pull requests over a single large one that targets multiple things at once.\r\n\r\n### When fixing a bug ...\r\n\r\nIf you have a good idea how to fix it, directly open a pull request. Otherwise you may want to open an issue first (at GitHub) and discuss it there. If you can reproduce the bug with simple enough code, please consider adding a Unit Test that fails to confirm the bug.\r\n\r\n### When extending features ...\r\n\r\nIf you\u0027re extending some feature which is similar and close to existing code, for example adding a new probability distribution or a new Bessel-related special function, it\u0027s fine to directly open a pull request. We\u0027re likely to accept such pulls.\r\n\r\n### When adding new features ...\r\n\r\nIf you intend to add completely new features, say some spatial routines for geometrical transformations, we recommend to [talk to us](https://discuss.mathdotnet.com/c/numerics) first. This is mostly to avoid wasting your time in case we decide not to accept it, or require major refactoring. If the features is quite small it is perfectly fine to just open a pull request though. Sometimes it\u0027s easier to just show code instead of lengthy explanations.\r\n\r\nNote that your work does not need to be finished or complete at the time you open the pull request (but please do mention this in the message), as GitHub pull requests are an excellent tool to discuss an early prototype or skeleton before it is fully implemented.\r\n\r\n### When you wish to contribute but do not know where to start ...\r\n\r\nIssues marked with \u0022up-for-grabs\u0022 should be good candidates for a first contribution, but you can start with whatever you wish. If you decide to work on an existing issue, consider to add a comment to mention you\u0027re working on it.\r\n\r\nWhat works very well is to try to build something with real world data that uses Math.NET Numerics: you either end up with a nice example that we would love to include or refer to, or you run into things which are missing, unintuitive, broken or just a bit weird, which we\u0027d love to hear about so we (or you?) can fix it.\r\n\r\nShould you stumble on weird English grammar or wording please do fix it - most of the contributors are not native English speakers. That includes this document.\r\n\r\n## What to Avoid\r\n\r\n**Code Reformatting and Refactoring:** \r\nPlease avoid starting with a major refactoring or any code reformatting without talking to us first.\r\n\r\n**Breaking Compatibility:** \r\nWe try to follow [semantic versioning](https://semver.org/), meaning that we cannot break compatibility until the next major version. Since Numerics intentionally permits straight access to raw algorithms, a lot of member declarations are public and thus cannot be modified. Instead of breaking compatibility, it is often possible to create a new better version side by side though and mark the original implementation as obsolete and scheduled for removal on the next major version.\r\n\r\n**Merges:** \r\nPlease avoid merging mainline back into your pull request branch. If you need to leverage some changes recently added to mainline, consider to rebase instead. In other words, please make sure your commits sit directly on top of a recent mainline master.\r\n"},{"uri":"https://numerics.mathdotnet.com/Contributors.html","title":"Math.NET Numerics Contributors\r\n","content":"Math.NET Numerics Contributors\r\n==============================\r\n\r\nThe Math.NET project is a community effort. We accept contributions and pull requests, but other support like submitting issues or helping the community are just as valuable. Why don\u0027t you join us as well?\r\n\r\n**Thanks for all the contributions!**\r\n\r\n### Maintainers\r\n\r\n- [Christoph R\u00FCegg](https://christoph.ruegg.name/) (@cdrnet) ([keybase.io/cdrnet](https://keybase.io/cdrnet))\r\n\r\n### Code Contributors\r\n\r\n*Essentially the output of \u0060git shortlog -sn\u0060 in original order. \r\nFeel free to add a link to your personal site/blog and/or twitter handle.*\r\n\r\n- [Christoph R\u00FCegg](https://christoph.ruegg.name/) (@cdrnet)\r\n- [Marcus Cuda](https://marcuscuda.com/) (@marcuscuda)\r\n- Jurgen Van Gael (@jvangael)\r\n- Scott Stephens\r\n- Ignas Anikevicius\r\n- Jong Hyun Kim\r\n- Alexander Karatarakis\r\n- Tobias Glaubach\r\n- Erik Oveg\u00E5rd\r\n- Thomas Ibel\r\n- Yoonku Hwang\r\n- Gustavo Guerra\r\n- Kuan Bartel\r\n- Larz White\r\n- Alexander T\u00E4schner\r\n- Hani Medhat\r\n- MaLiN2223\r\n- Matthew Johnson\r\n- manyue\r\n- David Prince\r\n- Evangelink\r\n- Frank A. Krueger\r\n- Andriy Bratiychuk\r\n- Febin\r\n- Jack Pappas\r\n- Jon Smit\r\n- Phil Cleveland\r\n- jnyrup\r\n- Aappo Pulkkinen\r\n- Artyom Baranovskiy\r\n- Ashley Messer\r\n- Candy Chiu\r\n- Evelina Gabasova\r\n- Superbest\r\n- lionpeloux\r\n- mjmckp\r\n- Anders Gustafsson\r\n- Gauthier Segay\r\n- Hythem Sidky\r\n- John C Barstow\r\n- Justin Needham\r\n- Ksero\r\n- P. van der Velde\r\n- Robin Neatherway\r\n- Tom McTiernan\r\n- mikael\r\n- Alex Hildebrand\r\n- Andrew Kazyrevich\r\n- Arthur\r\n- Ethar Alali\r\n- Feodor Fitsner\r\n- Iain McDonald\r\n- Jakub Bialogrodzki\r\n- Jon Larborn\r\n- Juri\r\n- Kyle Parrigan\r\n- Regis Portalez\r\n- Ryan Blackwell\r\n- bdodson\r\n- borfudin\r\n- Aixile\r\n- Albert Pang\r\n- AlexHild\r\n- Amaury Lev\u00E9\r\n- Andrew Willshire\r\n- BenHewins\r\n- Colin Green\r\n- Dan\r\n- Daniel Fox\r\n- David Falkner\r\n- Elias Abou Jaoude\r\n- Eric Salem\r\n- Florian Wechsung\r\n- Gregor959\r\n- Guney Ozsan\r\n- Iain Sproat\r\n- IgorK\r\n- Jakub Arnold\r\n- Jeff Mastry\r\n- Joel Sleppy\r\n- Konstantin Tretyakov\r\n- Kosei ABE\r\n- Lucas Godshalk\r\n- Manor Askenazi\r\n- MarcoRoss84\r\n- Martin Posch\r\n- Matt Heffron\r\n- Max Malook\r\n- Michael Holroyd\r\n- Michel de Ruiter\r\n- Mirth Hickford\r\n- Paul Varkey\r\n- Philip Gruber\r\n- Philipp Huber\r\n- RR\r\n- Ryan Grange\r\n- Sergey Kosukhin\r\n- Sunny Ahuwanya\r\n- Till Hoffmann\r\n- Tomas Petricek\r\n- ViK\r\n- VicPara\r\n- Volker Breuer\r\n- arthurvb\r\n- bbieniek\r\n- bstrausser\r\n- Christoph Alber\r\n- grovesNL\r\n- jb\r\n- kayan\r\n- liuzh\r\n- logophobia\r\n- Matthew Peacock\r\n- nyuriks\r\n- seahearman\r\n- teramonagi\r\n- vvavrychuk\r\n\r\n### Indirect Code Contributors\r\n\r\n*Code submitted by other means that does not appear in the git history. \r\nThis section is incomplete - let us know if we forgot something.*\r\n\r\n- Christian Woltering\r\n\r\n### dnAnalytics and Math.NET Iridium\r\n\r\n*Math.NET Numerics started by merging the dnAnalytics and Math.NET Iridium projects and their code base.*\r\n\r\n- [Marcus Cuda](https://marcuscuda.com/)\r\n- Jurgen Van Gael\r\n- Patrick van der Velde\r\n- [Christoph R\u00FCegg](https://christoph.ruegg.name/)\r\n- [Joann\u00E8s Vermorel](https://www.vermorel.com/)\r\n- Matthew Kitchin\r\n- Rana Ian\r\n- Andrew Kurochka\r\n- Thaddaeus Parker\r\n\r\n### Other Numerical Works, References \u0026 Resources\r\n\r\n*As inspiration, reference or more - depending on the licensing terms*\r\n\r\n- [ALGLIB](https://www.alglib.net/): Sergey Bochkanov\r\n- [Boost](https://www.boost.org/): John Maddock\r\n- [Netlib/Cephes Math Library](https://www.netlib.org/cephes/): Stephen L. Moshier\r\n- [Stand-alone code for numerical computing](https://www.johndcook.com/stand_alone_code.html): John D. Cook\r\n- [Miscellaneous Utility Library](https://www.yoda.arachsys.com/csharp/miscutil/): Marc Gravell, Jon Skeet\r\n- [NIST Digital Library of Mathematical Functions](https://www.johndcook.com/stand_alone_code.html)\r\n\r\n### Special Thanks\r\n\r\n*For other ways of support, documentation, website, feedback, software licenses, etc.*\r\n\r\n- Marcus Cuda (long time core contributor; license)\r\n- Jurgen Van Gael (long time core contributor)\r\n- F# Foundation \u0026 Community\r\n- Don Syme\r\n- Lokad SAS\r\n- Microsoft Corp\r\n- Xamarin (license)\r\n"},{"uri":"https://numerics.mathdotnet.com/CSV.html","title":"Delimited Text Files (CSV \u0026amp; TSV)\r\n","content":"Delimited Text Files (CSV \u0026 TSV)\r\n================================\r\n\r\nLikely the most common file format for tabular data, delimited files like CSV store data as text\r\nwith one line per row and values within rows separated by a comma.\r\nSuch text files are supported by virtually all software that deals with tabular data.\r\n\r\nExample:\r\n\r\n [lang=text]\r\n A,B,C\r\n 0.5,0.6,98.0\r\n 2.0,3.4,5.3\r\n\r\nUnfortunately there is no universal standard on what character is used as separator and how\r\nindividual values are formatted and escaped. CSV files traditionally use a comma as separator, but this\r\ncauses problems e.g. in Germany where the comma is used as decimal point in numbers. The tabulator\r\nproves to be a useful alternative, usually denoted by using the TSV extension instead of CSV.\r\nOther separators like semicolons or colons are common as well.\r\n\r\nMath.NET Numerics provides basic support for delimited files with the **MathNet.Numerics.Data.Text** package,\r\nwhich is available on NuGet as separate package and not included in the basic distribution.\r\n\r\n\r\nReading a matrix from a delimited file\r\n--------------------------------------\r\n\r\nThe \u0060DelimitedReader\u0060 class provides static functions to read a matrix from a file or string in delimited form.\r\nIt can read from:\r\n\r\n* **TextReader**: If you have your delimited data already in memory in a string,\r\n you can use this method using a StringReader.\r\n* **Stream**: read directly from a stream, e.g. a MemoryStream, FileStream or NetworkStream.\r\n* **File Path (string)**: read from a file, specified by the file system path.\r\n\r\nAll these functions expect the data type of the matrix to be generated as generic type argument.\r\nOnly Double, Single, Complex and Complex32 are supported.\r\n\r\nExample:\r\n\r\n [lang=csharp]\r\n using MathNet.Numerics.Data.Text;\r\n\r\n Matrix\u003Cdouble\u003E matrix = DelimitedReader.Read\u003Cdouble\u003E(\u0022data.csv\u0022, false, \u0022,\u0022, true);\r\n\r\nUnfortunately the lack of standard means that the parsing logic needs to be parametrized accordingly.\r\nThere are ways to automatically profile the provided file to find out the correct parameters automatically,\r\nbut for simplicity the Read functions expects those parameters explicitly as optional arguments:\r\n\r\n* **sparse**: Whether the the returned matrix should be constructed as sparse (true) or dense (false). \r\n Default: false.\r\n* **delimiter**: Number delimiter between numbers of the same line. Supports Regex groups. \r\n Default: \u0060\\s\u0060 (white space).\r\n* **hasHeaders**: Whether the first row contains column headers or not. If true, the first line will be skipped. \r\n Default: false.\r\n* **formatProvider**: The culture to use. It is often a good idea to use InvariantCulture,\r\n to make the format independent from the local culture. \r\n Default: null.\r\n\r\n\r\nWriting a matrix to a delimited file\r\n------------------------------------\r\n\r\nThe dual to the reader above is the \u0060DelimitedWriter\u0060 class that can serialize a matrix\r\nto a delimited text file, stream or TextWriter.\r\n\r\nThe static Write functions accept the following optional arguments to control the output format:\r\n\r\n* **delimiter**: Number delimiter to write between numbers of the same line. \r\n Default: \u0060\\t\u0060 (tabulator).\r\n* **columnHeaders**: list of column header strings, or null if no headers should be written. \r\n Default: null.\r\n* **format**: The number format to use on each element, similar to what can be provided to Double.ToString(). \r\n Default: null.\r\n* **formatProvider**: The culture to use. It is often a good idea to use InvariantCulture,\r\n to make the format independent from the local culture. \r\n Default: null.\r\n\r\nExample:\r\n\r\n [lang=csharp]\r\n DelimitedWriter.Write(\u0022data.csv\u0022, matrix, \u0022,\u0022);\r\n\r\n\r\nAlternatives\r\n------------\r\n\r\nThe data extension packages also offer other ways to serialize a matrix to a binary stream or file.\r\nAmong others:\r\n\r\n* [NIST MatrixMarket text files](MatrixMarket.html)\r\n* [MATLAB Level-5 Mat files](MatlabFiles.html)\r\n"},{"uri":"https://numerics.mathdotnet.com/DescriptiveStatistics.html","title":"Descriptive Statistics\r\n","content":" [hide]\r\n #I \u0022../../out/lib/net40\u0022\r\n #r \u0022MathNet.Numerics.dll\u0022\r\n #r \u0022MathNet.Numerics.FSharp.dll\u0022\r\n open System.Numerics\r\n open MathNet.Numerics\r\n open MathNet.Numerics.Statistics\r\n\r\nDescriptive Statistics\r\n======================\r\n\r\nInitialization\r\n--------------\r\n\r\nWe need to reference Math.NET Numerics and open the statistics namespace:\r\n\r\n [lang=csharp]\r\n using MathNet.Numerics.Statistics;\r\n\r\nUnivariate Statistical Analysis\r\n-------------------------------\r\n\r\nThe primary class for statistical analysis is \u0060Statistics\u0060 which provides common\r\ndescriptive statics as static extension methods to \u0060IEnumerable\u003Cdouble\u003E\u0060 sequences.\r\nHowever, various statistics can be computed much more efficiently if the data source\r\nhas known properties or structure, that\u0027s why the following classes provide specialized\r\nstatic implementations:\r\n\r\n* **ArrayStatistics** provides routines optimized for single-dimensional arrays. Some\r\n of these routines end with the \u0060Inplace\u0060 suffix, indicating that they reorder the\r\n input array slightly towards being sorted during execution - without fully sorting\r\n them, which could be expensive.\r\n* **SortedArrayStatistics** provides routines optimized for an array sorting ascendingly.\r\n Especially order-statistics are very efficient this way, some even with constant time complexity.\r\n* **StreamingStatistics** processes large amounts of data without keeping them in memory.\r\n Useful if data larger than local memory is streamed directly from a disk or network.\r\n\r\nAnother alternative, in case you need to gather a whole set of statistical characteristics\r\nin one pass, is provided by the \u0060DescriptiveStatistics\u0060 class:\r\n\r\n [lang=csharp]\r\n var samples = new ChiSquare(5).Samples().Take(1000);\r\n var statistics = new DescriptiveStatistics(samples);\r\n\r\n var largestElement = statistics.Maximum;\r\n var smallestElement = statistics.Minimum;\r\n var median = statistics.Median;\r\n\r\n var mean = statistics.Mean;\r\n var variance = statistics.Variance;\r\n var stdDev = statistics.StandardDeviation;\r\n\r\n var kurtosis = statistics.Kurtosis;\r\n var skewness = statistics.Skewness;\r\n\r\n\r\nMinimum \u0026 Maximum\r\n-----------------\r\n\r\nThe minimum and maximum values of a sample set can be evaluated with the \u0060Minimum\u0060 and \u0060Maximum\u0060\r\nfunctions of all four classes: \u0060Statistics\u0060, \u0060ArrayStatistics\u0060, \u0060SortedArrayStatistics\u0060\r\nand \u0060StreamingStatistics\u0060. The one in \u0060SortedArrayStatistics\u0060 is the fastest with constant\r\ntime complexity, but expects the array to be sorted ascendingly.\r\n\r\nBoth min and max are directly affected by outliers and are therefore no robust statistics at all.\r\nFor a more robust alternative, consider using Quantiles instead.\r\n\r\n [lang=csharp]\r\n var samples = new ChiSquare(5).Samples().Take(1000).ToArray();\r\n var largestElement = samples.Maximum();\r\n var smallestElement = samples.Minimum();\r\n\r\n\r\nMean\r\n----\r\n\r\nThe *arithmetic mean* or *average* of the provided samples. In statistics, the sample mean is\r\na measure of the central tendency and estimates the expected value of the distribution.\r\nThe mean is affected by outliers, so if you need a more robust estimate consider to use the Median instead.\r\n\r\n\u0060Statistics.Mean(data)\u0060\r\n\u0060StreamingStatistics.Mean(stream)\u0060\r\n\u0060ArrayStatistics.Mean(data)\u0060\r\n\r\n$$$\r\n\\overline{x} = \\frac{1}{N}\\sum_{i=1}^N x_i\r\n\r\n [lang=fsharp]\r\n let whiteNoise = Generate.Normal(1000, mean=10.0, standardDeviation=2.0)\r\n // [fsi:val samples : float [] = [|12.90021939; 9.631515037; 7.810008046; 14.13301053; ...|] ]\r\n Statistics.Mean whiteNoise\r\n // [fsi:val it : float = 10.02162347]\r\n\r\n let wave = Generate.Sinusoidal(1000, samplingRate=100., frequency=5., amplitude=0.5)\r\n Statistics.Mean wave\r\n // [fsi:val it : float = -4.133520783e-17]\r\n\r\nVariance and Standard Deviation\r\n-------------------------------\r\n\r\nVariance $\\sigma^2$ and the Standard Deviation $\\sigma$ are measures of how far the samples are spread out.\r\n\r\nIf the whole population is available, the functions with the Population-prefix\r\n will evaluate the respective measures with an $N$ normalizer for a population of size $N$.\r\n\r\n\u0060Statistics.PopulationVariance(population)\u0060\r\n\u0060Statistics.PopulationStandardDeviation(population)\u0060\r\n\r\n$$$\r\n\\sigma^2 = \\frac{1}{N}\\sum_{i=1}^N (x_i - \\mu)^2\r\n\r\nOn the other hand, if only a sample of the full population is available, the functions\r\nwithout the Population-prefix will estimate unbiased population measures by applying\r\nBessel\u0027s correction with an $N-1$ normalizer to a sample set of size $N$.\r\n\r\n\u0060Statistics.Variance(samples)\u0060\r\n\u0060Statistics.StandardDeviation(samples)\u0060\r\n\r\n$$$\r\ns^2 = \\frac{1}{N-1}\\sum_{i=1}^N (x_i - \\overline{x})^2\r\n\r\n [lang=fsharp]\r\n Statistics.Variance whiteNoise\r\n // [fsi:val it : float = 3.819436094]\r\n Statistics.StandardDeviation whiteNoise\r\n // [fsi:val it : float = 1.954337764]\r\n\r\n Statistics.Variance wave\r\n // [fsi:val it : float = 0.1251251251]\r\n\r\n#### Combined Routines\r\n\r\nSince mean and variance are often needed together, there are routines\r\nthat evaluate both in a single pass:\r\n\r\n\u0060Statistics.MeanVariance(samples)\u0060\r\n\u0060ArrayStatistics.MeanVariance(samples)\u0060\r\n\u0060StreamingStatistics.MeanVariance(samples)\u0060\r\n\r\n [lang=fsharp]\r\n Statistics.MeanVariance whiteNoise\r\n // [fsi:val it : float * float = (10.02162347, 3.819436094)]\r\n\r\nCovariance\r\n----------\r\n\r\nThe sample covariance is an estimation of the Covariance, a measure of how much two random\r\nvariables change together. Similarly to the variance above, there are two versions in order to\r\napply Bessel\u0027s correction to bias in case of sample data.\r\n\r\n\u0060Statistics.Covariance(samples1, samples2)\u0060\r\n\r\n$$$\r\nq = \\frac{1}{N-1}\\sum_{i=1}^N (x_i - \\overline{x})(y_i - \\overline{y})\r\n\r\n\u0060Statistics.PopulationCovariance(population1, population2)\u0060\r\n\r\n$$$\r\nq = \\frac{1}{N}\\sum_{i=1}^N (x_i - \\mu_x)(y_i - \\mu_y)\r\n\r\n [lang=fsharp]\r\n Statistics.Covariance(whiteNoise, whiteNoise)\r\n // [fsi:val it : float = 3.819436094]\r\n Statistics.Covariance(whiteNoise, wave)\r\n // [fsi:val it : float = 0.04397985084]\r\n\r\nOrder Statistics\r\n----------------\r\n\r\n#### Order Statistic\r\n\r\nThe k-th order statistic of a sample set is the k-th smallest value. Note that,\r\nas an exception to most of Math.NET Numerics, the order k is one-based, meaning\r\nthe smallest value is the order statistic of order 1 (there is no order 0).\r\n\r\n\u0060Statistics.OrderStatistic(data, order)\u0060\r\n\u0060SortedArrayStatistics.OrderStatistic(data, order)\u0060\r\n\r\nIf the samples are sorted ascendingly, this is trivial and can be evaluated in constant time,\r\nwhich is what the \u0060SortedArrayStatistics\u0060 implementation does.\r\n\r\nIf you have the samples in an array which is not (guaranteed to be) sorted,\r\nbut if it is fine if the array does incrementally get sorted over multiple calls,\r\nyou can also use the following in-place implementation. It is usually faster\r\nthan fully sorting the array, unless you need to compute it for more than a handful orders.\r\n\r\n\u0060ArrayStatistics.OrderStatisticInplace(data, order)\u0060\r\n\r\nFor convenience there\u0027s also an option that returns a function \u0060Func\u003Cint, double\u003E\u0060,\r\nmapping from order to the resulting order statistic. Internally it sorts a copy of the\r\nprovided data and then on each invocation uses efficient sorted algorithms:\r\n\r\n\u0060Statistics.OrderStatisticFunc(data)\u0060\r\n\r\nSuch Inplace and Func variants are a common pattern throughout the Statistics class\r\nand also the rest of the library.\r\n\r\n [lang=fsharp]\r\n Statistics.OrderStatistic(whiteNoise, 1)\r\n // [fsi:val it : float = 3.633070184]\r\n Statistics.OrderStatistic(whiteNoise, 1000)\r\n // [fsi:val it : float = 16.65183566]\r\n\r\n let os = Statistics.orderStatisticFunc whiteNoise\r\n os 250\r\n // [fsi:val it : float = 8.645491746]\r\n os 500\r\n // [fsi:val it : float = 10.11872428]\r\n os 750\r\n // [fsi:val it : float = 11.33170746]\r\n\r\n#### Median\r\n\r\nMedian is a robust indicator of central tendency and much less affected by outliers\r\nthan the sample mean. The median is estimated by the value exactly in the middle of\r\nthe sorted set of samples and thus separating the higher half of the data from the lower half.\r\n\r\n\u0060Statistics.Median(data)\u0060\r\n\u0060SortedArrayStatistics.Median(data)\u0060\r\n\u0060ArrayStatistics.MedianInplace(data)\u0060\r\n\r\nThe median is only unique if the sample size is odd. This implementation internally\r\nuses the default quantile definition, which is equivalent to mode 8 in R and is approximately\r\nmedian-unbiased regardless of the sample distribution. If you need another convention, use\r\n\u0060QuantileCustom\u0060 instead, see below for details.\r\n\r\n [lang=fsharp]\r\n Statistics.Median whiteNoise\r\n // [fsi:val it : float = 10.11872428]\r\n Statistics.Median wave\r\n // [fsi:val it : float = -2.452600839e-16]\r\n\r\n#### Quartiles and the 5-number summary\r\n\r\nQuartiles group the ascendingly sorted data into four equal groups, where each\r\ngroup represents a quarter of the data. The lower quartile is estimated by\r\nthe middle number between the first two groups and the upper quartile by the middle\r\nnumber between the remaining two groups. The middle number between the two middle groups\r\nestimates the median as discussed above.\r\n\r\n\u0060Statistics.LowerQuartile(data)\u0060\r\n\u0060Statistics.UpperQuartile(data)\u0060\r\n\u0060SortedArrayStatistics.LowerQuartile(data)\u0060\r\n\u0060SortedArrayStatistics.UpperQuartile(data)\u0060\r\n\u0060ArrayStatistics.LowerQuartileInplace(data)\u0060\r\n\u0060ArrayStatistics.UpperQuartileInplace(data)\u0060\r\n\r\n [lang=fsharp]\r\n Statistics.LowerQuartile whiteNoise\r\n // [fsi:val it : float = 8.645491746]\r\n Statistics.UpperQuartile whiteNoise\r\n // [fsi:val it : float = 11.33213732]\r\n\r\nUsing that data we can provide a useful set of indicators usually named 5-number summary,\r\nwhich consists of the minimum value, the lower quartile, the median, the upper quartile and\r\nthe maximum value. All these values can be visualized in the popular box plot diagrams.\r\n\r\n\u0060Statistics.FiveNumberSummary(data)\u0060\r\n\u0060SortedArrayStatistics.FiveNumberSummary(data)\u0060\r\n\u0060ArrayStatistics.FiveNumberSummaryInplace(data)\u0060\r\n\r\n [lang=fsharp]\r\n Statistics.FiveNumberSummary whiteNoise\r\n // [fsi:val it : float [] = [|3.633070184; 8.645937823; 10.12165054; 11.33213732; 16.65183566|] ]\r\n Statistics.FiveNumberSummary wave\r\n // [fsi:val it : float [] = [|-0.5; -0.3584185509; -2.452600839e-16; 0.3584185509; 0.5|] ]\r\n\r\nThe difference between the upper and the lower quartile is called inter-quartile range (IQR)\r\nand is a robust indicator of spread. In box plots the IQR is the total height of the box.\r\n\r\n\u0060Statistics.InterquartileRange(data)\u0060\r\n\u0060SortedArrayStatistics.InterquartileRange(data)\u0060\r\n\u0060ArrayStatistics.InterquartileRangeInplace(data)\u0060\r\n\r\nJust like median, quartiles use the default R8 quantile definition internally.\r\n\r\n [lang=fsharp]\r\n Statistics.InterquartileRange whiteNoise\r\n // [fsi:val it : float = 2.686199498]\r\n\r\n#### Percentiles\r\n\r\nPercentiles extend the concept further by grouping the sorted values into 100\r\nequal groups and looking at the 101 places (0,1,..,100) between and around them.\r\nThe 0-percentile represents the minimum value, 25 the first quartile, 50 the median,\r\n75 the upper quartile and 100 the maximum value.\r\n\r\n\u0060Statistics.Percentile(data, p)\u0060\r\n\u0060Statistics.PercentileFunc(data)\u0060\r\n\u0060SortedArrayStatistics.Percentile(data, p)\u0060\r\n\u0060ArrayStatistics.PercentileInplace(data, p)\u0060\r\n\r\nJust like median, percentiles use the default R8 quantile definition internally.\r\n\r\n [lang=fsharp]\r\n Statistics.Percentile(whiteNoise, 5)\r\n // [fsi:val it : float = 6.693373507]\r\n Statistics.Percentile(whiteNoise, 98)\r\n // [fsi:val it : float = 13.97580653]\r\n\r\n#### Quantiles\r\n\r\nInstead of grouping into 4 or 100 boxes, quantiles generalize the concept to an infinite number\r\nof boxes and thus to arbitrary real numbers $\\tau$ between 0.0 and 1.0, where 0.0 represents the\r\nminimum value, 0.5 the median and 1.0 the maximum value. Quantiles are closely related to\r\nthe inverse cumulative distribution function of the sample distribution.\r\n\r\n\u0060Statistics.Quantile(data, tau)\u0060\r\n\u0060Statistics.QuantileFunc(data)\u0060\r\n\u0060SortedArrayStatistics.Quantile(data, tau)\u0060\r\n\u0060ArrayStatistics.QuantileInplace(data, tau)\u0060\r\n\r\n [lang=fsharp]\r\n Statistics.Quantile(whiteNoise, 0.98)\r\n // [fsi:val it : float = 13.97580653]\r\n\r\n#### Quantile Conventions and Compatibility\r\n\r\nRemember that all these descriptive statistics do not *compute* but merely *estimate*\r\nstatistical indicators of the value distribution. In the case of quantiles,\r\nthere is usually not a single number between the two groups specified by $\\tau$.\r\nThere are multiple ways to deal with this: the R project supports 9 modes and Mathematica\r\nand SciPy have their own way to parametrize the behavior.\r\n\r\nThe \u0060QuantileCustom\u0060 functions support all 9 modes from the R-project, which includes the one\r\nused by Microsoft Excel, and also the 4-parameter variant of Mathematica:\r\n\r\n\u0060Statistics.QuantileCustom(data, tau, definition)\u0060\r\n\u0060Statistics.QuantileCustomFunc(data, definition)\u0060\r\n\u0060SortedArrayStatistics.QuantileCustom(data, tau, a, b, c, d)\u0060\r\n\u0060SortedArrayStatistics.QuantileCustom(data, tau, definition)\u0060\r\n\u0060ArrayStatistics.QuantileCustomInplace(data, tau, a, b, c, d)\u0060\r\n\u0060ArrayStatistics.QuantileCustomInplace(data, tau, definition)\u0060\r\n\r\nThe \u0060QuantileDefinition\u0060 enumeration has the following options:\r\n\r\n* **R1**, SAS3, EmpiricalInvCDF\r\n* **R2**, SAS5, EmpiricalInvCDFAverage\r\n* **R3**, SAS2, Nearest\r\n* **R4**, SAS1, California\r\n* **R5**, Hydrology, Hazen\r\n* **R6**, SAS4, Nist, Weibull, SPSS\r\n* **R7**, Excel, Mode, S\r\n* **R8**, Median, Default\r\n* **R9**, Normal\r\n\r\n [lang=fsharp]\r\n Statistics.QuantileCustom(whiteNoise, 0.98, QuantileDefinition.R3)\r\n // [fsi:val it : float = 13.97113209]\r\n Statistics.QuantileCustom(whiteNoise, 0.98, QuantileDefinition.Excel)\r\n // [fsi:val it : float = 13.97127374]\r\n\r\nRank Statistics\r\n---------------\r\n\r\n#### Ranks\r\n\r\nRank statistics are the counterpart to order statistics. The \u0060Ranks\u0060 function evaluates the rank\r\nof each sample and returns them as an array of doubles. The return type is double instead of int\r\nin order to deal with ties, if one of the values appears multiple times.\r\nSimilar to \u0060QuantileDefinition\u0060, the \u0060RankDefinition\u0060 enumeration controls how ties should be handled:\r\n\r\n* **Average**, Default: Replace ties with their mean (causing non-integer ranks).\r\n* **Min**, Sports: Replace ties with their minimum, as typical in sports ranking.\r\n* **Max**: Replace ties with their maximum.\r\n* **First**: Permutation with increasing values at each index of ties.\r\n* **EmpiricalCDF**\r\n\r\n\u0060Statistics.Ranks(data, definition)\u0060\r\n\u0060SortedArrayStatistics.Ranks(data, definition)\u0060\r\n\u0060ArrayStatistics.RanksInplace(data, definition)\u0060\r\n\r\n [lang=fsharp]\r\n Statistics.Ranks(whiteNoise)\r\n // [fsi:val it : float [] = [|634.0; 736.0; 405.0; 395.0; 197.0; 167.0; 722.0; 44.0; ...|] ]\r\n Statistics.Ranks([| 13.0; 14.0; 11.0; 12.0; 13.0 |], RankDefinition.Average)\r\n // [fsi:val it : float [] = [|3.5; 5.0; 1.0; 2.0; 3.5|] ]\r\n Statistics.Ranks([| 13.0; 14.0; 11.0; 12.0; 13.0 |], RankDefinition.Sports)\r\n // [fsi:val it : float [] = [|3.0; 5.0; 1.0; 2.0; 3.0|] ]\r\n\r\n#### Quantile Rank\r\n\r\nCounterpart of the \u0060Quantile\u0060 function, estimates $\\tau$ of the provided $\\tau$-quantile value\r\n$x$ from the provided samples. The $\\tau$-quantile is the data value where the cumulative distribution\r\nfunction crosses $\\tau$.\r\n\r\n\u0060Statistics.QuantileRank(data, x, definition)\u0060\r\n\u0060Statistics.QuantileRankFunc(data, definition)\u0060\r\n\u0060SortedArrayStatistics.QuantileRank(data, x, definition)\u0060\r\n\r\n [lang=fsharp]\r\n Statistics.QuantileRank(whiteNoise, 13.0)\r\n // [fsi:val it : float = 0.9370045563]\r\n Statistics.QuantileRank(whiteNoise, 6.7, RankDefinition.Average)\r\n // [fsi:val it : float = 0.04960610389]\r\n\r\nEmpirical Distribution Functions\r\n--------------------------------\r\n\r\n\u0060Statistics.EmpiricalCDF(data, x)\u0060\r\n\u0060Statistics.EmpiricalCDFFunc(data)\u0060\r\n\u0060Statistics.EmpiricalInvCDF(data, tau)\u0060\r\n\u0060Statistics.EmpiricalInvCDFFunc(data)\u0060\r\n\u0060SortedArrayStatistics.EmpiricalCDF(data, x)\u0060\r\n\r\n [lang=fsharp]\r\n let ecdf = Statistics.EmpiricalCDFFunc whiteNoise\r\n Generate.LinearSpacedMap(20, start=3.0, stop=17.0, map=ecdf)\r\n // [fsi:val it : float [] =]\r\n // [fsi: [|0.0; 0.001; 0.002; 0.005; 0.022; 0.05; 0.094; 0.172; 0.278; 0.423; 0.555; ]\r\n // [fsi: 0.705; 0.843; 0.921; 0.944; 0.983; 0.992; 0.997; 0.999; 1.0|] ]\r\n\r\n let eicdf = Statistics.empiricalInvCDFFunc whiteNoise\r\n [ for tau in 0.0..0.05..1.0 -\u003E eicdf tau ]\r\n // [fsi:val it : float [] =]\r\n // [fsi: [3.633070184; 6.682142043; 7.520000817; 8.040513497; 8.347587493; ]\r\n // [fsi: 8.645491746; 9.02681611; 9.298987151; 9.522627142; 9.819352699; 10.11872428; ]\r\n // [fsi: 10.35991046; 10.57530906; 10.8259542; 11.08605473; 11.33170746; 11.54356436; ]\r\n // [fsi: 11.90973541; 12.4294346; 13.36889423; 16.65183566] ]\r\n\r\nHistograms\r\n----------\r\n\r\nA histogram can be computed using the [Histogram][hist] class. Its constructor takes\r\nthe samples enumerable, the number of buckets to create, plus optionally the range\r\n(minimum, maximum) of the sample data if available.\r\n\r\n [hist]: https://numerics.mathdotnet.com/api/MathNet.Numerics.Statistics/Histogram.htm\r\n\r\n [lang=csharp]\r\n var histogram = new Histogram(samples, 10);\r\n var bucket3count = histogram[2].Count;\r\n\r\n\r\nCorrelation\r\n-----------\r\n\r\nThe \u0060Correlation\u0060 class supports computing Pearson\u0027s product-momentum and Spearman\u0027s ranked\r\ncorrelation coefficient, as well as their correlation matrix for a set of vectors.\r\n\r\nCode Sample: Computing the correlation coefficient of 1000 samples of f(x) = 2x and g(x) = x^2:\r\n\r\n [lang=csharp]\r\n double[] dataF = Generate.LinearSpacedMap(1000, 0, 100, x =\u003E 2*x);\r\n double[] dataG = Generate.LinearSpacedMap(1000, 0, 100, x =\u003E x*x);\r\n double correlation = Correlation.Pearson(dataF, dataG);\r\n"},{"uri":"https://numerics.mathdotnet.com/Distance.html","title":"Distance Metrics\r\n","content":"Distance Metrics\r\n================\r\n\r\nA metric or distance function is a function $d(x,y)$ that defines the distance\r\nbetween elements of a set as a non-negative real number. If the distance is zero, both elements are equivalent\r\nunder that specific metric. Distance functions thus provide a way to measure how close two elements are, where elements\r\ndo not have to be numbers but can also be vectors, matrices or arbitrary objects. Distance functions are often used\r\nas error or cost functions to be minimized in an optimization problem.\r\n\r\nThere are multiple ways to define a metric on a set. A typical distance for real numbers is the absolute difference,\r\n$ d : (x, y) \\mapsto |x-y| $. But a scaled version of the absolute difference, or even $d(x, y) = \\begin{cases} 0 \u0026\\mbox{if } x = y \\\\ 1 \u0026 \\mbox{if } x \\ne y. \\end{cases}$\r\nare valid metrics as well. Every normed vector space induces a distance given by $d(\\vec x, \\vec y) = \\|\\vec x - \\vec y\\|$.\r\n\r\nMath.NET Numerics provides the following distance functions on vectors and arrays:\r\n\r\n\r\nSum of Absolute Difference (SAD)\r\n--------------------------------\r\n\r\n\u003Cimg src=\u0022DistanceSAD.png\u0022 style=\u0022width:87px; height:87px; float:left; margin:10px 10px 10px 0;\u0022 /\u003E\r\n\r\nThe sum of absolute difference is equivalent to the $L_1$-norm of the difference, also known as Manhattan- or Taxicab-norm.\r\nThe \u0060abs\u0060 function makes this metric a bit complicated to deal with analytically, but it is more robust than SSD.\r\n\r\n$$$\r\nd_{\\mathbf{SAD}} : (x, y) \\mapsto \\|x-y\\|_1 = \\sum_{i=1}^{n} |x_i-y_i|\r\n\r\n [lang=csharp]\r\n double d = Distance.SAD(x, y);\r\n\r\n\r\nSum of Squared Difference (SSD)\r\n-------------------------------\r\n\r\n\u003Cimg src=\u0022DistanceSSD.png\u0022 style=\u0022width:87px; height:87px; float:left; margin:10px 10px 10px 0;\u0022 /\u003E\r\n\r\nThe sum of squared difference is equivalent to the squared $L_2$-norm, also known as Euclidean norm.\r\nIt is therefore also known as Squared Euclidean distance.\r\nThis is the fundamental metric in least squares problems and linear algebra. The absence of the \u0060abs\u0060\r\nfunction makes this metric convenient to deal with analytically, but the squares cause it to be very\r\nsensitive to large outliers.\r\n\r\n$$$\r\nd_{\\mathbf{SSD}} : (x, y) \\mapsto \\|x-y\\|_2^2 = \\langle x-y, x-y\\rangle = \\sum_{i=1}^{n} (x_i-y_i)^2\r\n\r\n [lang=csharp]\r\n double d = Distance.SSD(x, y);\r\n\r\n\r\nMean-Absolute Error (MAE)\r\n-------------------------\r\n\r\n\u003Cimg src=\u0022DistanceMAE.png\u0022 style=\u0022width:87px; height:87px; float:left; margin:10px 10px 10px 0;\u0022 /\u003E\r\n\r\nThe mean absolute error is a normalized version of the sum of absolute difference.\r\n\r\n$$$\r\nd_{\\mathbf{MAE}} : (x, y) \\mapsto \\frac{d_{\\mathbf{SAD}}}{n} = \\frac{\\|x-y\\|_1}{n} = \\frac{1}{n}\\sum_{i=1}^{n} |x_i-y_i|\r\n\r\n [lang=csharp]\r\n double d = Distance.MAE(x, y);\r\n\r\n\r\nMean-Squared Error (MSE)\r\n------------------------\r\n\r\n\u003Cimg src=\u0022DistanceMSE.png\u0022 style=\u0022width:87px; height:87px; float:left; margin:10px 10px 10px 0;\u0022 /\u003E\r\n\r\nThe mean squared error is a normalized version of the sum of squared difference.\r\n\r\n$$$\r\nd_{\\mathbf{MSE}} : (x, y) \\mapsto \\frac{d_{\\mathbf{SSD}}}{n} = \\frac{\\|x-y\\|_2^2}{n} = \\frac{1}{n}\\sum_{i=1}^{n} (x_i-y_i)^2\r\n\r\n [lang=csharp]\r\n double d = Distance.MSE(x, y);\r\n\r\n\r\nEuclidean Distance\r\n------------------\r\n\r\n\u003Cimg src=\u0022DistanceEuclidean.png\u0022 style=\u0022width:87px; height:87px; float:left; margin:10px 10px 10px 0;\u0022 /\u003E\r\n\r\nThe euclidean distance is the $L_2$-norm of the difference, a special case of the Minkowski distance with p=2.\r\nIt is the natural distance in a geometric interpretation.\r\n\r\n$$$\r\nd_{\\mathbf{2}} : (x, y) \\mapsto \\|x-y\\|_2 = \\sqrt{d_{\\mathbf{SSD}}} = \\sqrt{\\sum_{i=1}^{n} (x_i-y_i)^2}\r\n\r\n [lang=csharp]\r\n double d = Distance.Euclidean(x, y);\r\n\r\n\r\nManhattan Distance\r\n------------------\r\n\r\n\u003Cimg src=\u0022DistanceManhattan.png\u0022 style=\u0022width:87px; height:87px; float:left; margin:10px 10px 10px 0;\u0022 /\u003E\r\n\r\nThe Manhattan distance is the $L_1$-norm of the difference, a special case of the Minkowski distance with p=1\r\nand equivalent to the sum of absolute difference.\r\n\r\n$$$\r\nd_{\\mathbf{1}} \\equiv d_{\\mathbf{SAD}} : (x, y) \\mapsto \\|x-y\\|_1 = \\sum_{i=1}^{n} |x_i-y_i|\r\n\r\n [lang=csharp]\r\n double d = Distance.Manhattan(x, y);\r\n\r\n\r\nChebyshev Distance\r\n------------------\r\n\r\n\u003Cimg src=\u0022DistanceChebyshev.png\u0022 style=\u0022width:87px; height:87px; float:left; margin:10px 10px 10px 0;\u0022 /\u003E\r\n\r\nThe Chebyshev distance is the $L_\\infty$-norm of the difference, a special case of the Minkowski distance\r\nwhere p goes to infinity. It is also known as Chessboard distance. \r\n\r\n$$$\r\nd_{\\mathbf{\\infty}} : (x, y) \\mapsto \\|x-y\\|_\\infty = \\lim_{p \\rightarrow \\infty}\\bigg(\\sum_{i=1}^{n} |x_i-y_i|^p\\bigg)^\\frac{1}{p} = \\max_{i} |x_i-y_i|\r\n\r\n [lang=csharp]\r\n double d = Distance.Chebyshev(x, y);\r\n\r\n\r\nMinkowski Distance\r\n------------------\r\n\r\n\u003Cimg src=\u0022DistanceMinkowski3.png\u0022 style=\u0022width:87px; height:87px; float:left; margin:10px 10px 10px 0;\u0022 /\u003E\r\n\r\nThe Minkowski distance is the generalized $L_p$-norm of the difference.\r\nThe contour plot on the left demonstrates the case of p=3.\r\n\r\n$$$\r\nd_{\\mathbf{p}} : (x, y) \\mapsto \\|x-y\\|_p = \\bigg(\\sum_{i=1}^{n} |x_i-y_i|^p\\bigg)^\\frac{1}{p}\r\n\r\n [lang=csharp]\r\n double d = Distance.Minkowski(p, x, y);\r\n\r\n\r\nCanberra Distance\r\n-----------------\r\n\r\n\u003Cimg src=\u0022DistanceCanberra.png\u0022 style=\u0022width:87px; height:87px; float:left; margin:10px 10px 10px 0;\u0022 /\u003E\r\n\r\nThe Canberra distance is a weighted version of the Manhattan distance, introduced and refined 1967 by Lance, Williams and Adkins.\r\nIt is often used for data scattered around an origin, as it is biased for measures around the origin and very sensitive for values close to zero.\r\n\r\n$$$\r\nd_{\\mathbf{CAD}} : (x, y) \\mapsto \\sum_{i=1}^{n} \\frac{|x_i-y_i|}{|x_i|\u002B|y_i|}\r\n\r\n [lang=csharp]\r\n double d = Distance.Canberra(x, y);\r\n\r\n\r\nCosine Distance\r\n---------------\r\n\r\n\u003Cimg src=\u0022DistanceCosine.png\u0022 style=\u0022width:87px; height:87px; float:left; margin:10px 10px 10px 0;\u0022 /\u003E\r\n\r\nThe cosine distance contains the dot product scaled by the product of the Euclidean distances from the origin.\r\nIt represents the angular distance of two vectors while ignoring their scale.\r\n\r\n$$$\r\nd_{\\mathbf{cos}} : (x, y) \\mapsto 1-\\frac{\\langle x, y\\rangle}{\\|x\\|_2\\|y\\|_2} = 1-\\frac{\\sum_{i=1}^{n} x_i y_i}{\\sqrt{\\sum_{i=1}^{n} x_i^2}\\sqrt{\\sum_{i=1}^{n} y_i^2}}\r\n\r\n [lang=csharp]\r\n double d = Distance.Cosine(x, y);\r\n\r\n\r\nPearson\u0027s Distance\r\n------------------\r\n\r\n\u003Cimg src=\u0022DistancePearson.png\u0022 style=\u0022width:87px; height:87px; float:left; margin:10px 10px 10px 0;\u0022 /\u003E\r\n\r\nThe Pearson distance is a correlation distance based on Pearson\u0027s product-momentum correlation coefficient\r\nof the two sample vectors. Since the correlation coefficient falls between [-1, 1], the Pearson distance\r\nlies in [0, 2] and measures the linear relationship between the two vectors.\r\n\r\n$$$\r\nd_{\\mathbf{Pearson}} : (x, y) \\mapsto 1 - \\mathbf{Corr}(x, y)\r\n\r\n [lang=csharp]\r\n double d = Distance.Pearson(x, y);\r\n\r\n\r\nHamming Distance\r\n----------------\r\n\r\nThe hamming distance represents the number of entries in the two sample vectors which are different.\r\nIt is a fundamental distance measure in information theory but less relevant in non-integer numerical problems.\r\n\r\n [lang=csharp]\r\n double d = Distance.Hamming(x, y);\r\n"},{"uri":"https://numerics.mathdotnet.com/Euclid.html","title":"Euclid \u0026amp; Number Theory\r\n","content":"Euclid \u0026 Number Theory\r\n======================\r\n\r\nThe static \u0060Euclid\u0060 class in the \u0060MathNet.Numerics\u0060 namespace provides routines related\r\nto the domain of integers.\r\n\r\n\r\nRemainder vs. Canonical Modulus\r\n-------------------------------\r\n\r\nRemainder and modulus are closely related operations with a long tradition of confusing \r\non with the other. The % operator in most computer languages implements one of the two,\r\nbut some even leave which one as an implementation detail (e.g. C-1990).\r\n\r\n*Warning: In C#, like most languages, % is the remainder operator, not the modulus!*\r\n\r\n\r\n#### Remainder\r\n\r\nThe **remainder** is the amount left over after performing the division of a dividend\r\nby a divisor, $\\frac{dividend}{divisor}$, which do not divide evenly, that is,\r\nwhere the result of the division cannot be expressed as an integer. It is thus natural\r\nthat the **remainder has the sign of the dividend**.\r\n\r\nIn C# and F#, the remainder is available as \u0060%\u0060 operator, in VB as \u0060Mod\u0060.\r\nAlternatively you can use the Reminder function:\r\n\r\n [lang=csharp]\r\n Euclid.Remainder( 5, 3); // = 2, such that 5 = 1*3 \u002B 2\r\n Euclid.Remainder(-5, 3); // = -2, such that -5 = -1*3 - 2\r\n Euclid.Remainder( 5, -3); // = 2, such that 5 = -1*-3 \u002B 2\r\n Euclid.Remainder(-5, -3); // = -2, such that -5 = 1*-3 - 2\r\n\r\n\r\n#### Modulus\r\n\r\nOn the other hand, in modular arithmetic numbers \u0022wrap around\u0022 upon reaching a certain\r\nvalue n, or when crossing zero. Two real numbers are said to be *congruent modulo n*\r\nwhen their difference is an integer multiple of n. The modulo operator normalizes the dividend\r\nto the fundamental or smallest values congruent modulo n, where n is the divisor, and thus\r\nto the interval from 0 to n (including 0 but excluding n, possibly negative). It is thus natural that\r\nthe **modulus always has the sign of the divisor**.\r\n\r\n [lang=csharp]\r\n Euclid.Modulus( 5, 3); // = 2, congruent modulo 3 by 5 - 1*3\r\n Euclid.Modulus(-5, 3); // = 1, congruent modulo 3 by -5 \u002B 2*3\r\n Euclid.Modulus( 5, -3); // = -1, congruent modulo -3 by 5 \u002B 2*-3\r\n Euclid.Modulus(-5, -3); // = -2, congruent modulo -3 by -5 - 1*-3\r\n\r\nA typical case where the modulus appears in daily life is when grouping students into 3 groups\r\nby letting them line up and count through as 0 1 2 0 1 2 0 1 2 etc. This way, each student will\r\nend up in the group of their order within the line modulus 3.\r\n\r\n\r\nInteger Properties\r\n------------------\r\n\r\n#### Even or Odd?\r\n\r\nVery simple question yet still somewhat error-prone to implement such that it works correctly\r\nfor both positive and negative integers: is a number even or odd?\r\n\r\n* \u0060IsEven(number)\u0060\r\n* \u0060IsOdd(number)\u0060\r\n\r\n\r\n#### Powers of two and Squares\r\n\r\nPowers of two are prevalent in computer engineering. For performance reasons it is often preferable\r\nto align data in blocks where the size is a power of two, i.e. $2^k$. The \u0060CeilingToPowerOfTwo\u0060 function\r\nhelps in such situations by finding the smallest perfect power of two larger than or equal to\r\nthe provided argument. There is also \u0060IsPowerOfTwo\u0060 to determine whether a number is such a power of two,\r\nand \u0060PowerOfTwo\u0060 to compute it efficiently.\r\n\r\nWhen switching the operands of $2^k$ we get the square $k^2$. \u0060IsPerfectSquare\u0060 determines whether\r\nthe integer argument is a perfect square, i.e. a square of an integer.\r\n\r\n\r\nEuclid\u0027s Algorithm\r\n------------------\r\n\r\n#### Greatest Common Divisor\r\n\r\nThe \u0060GreatestCommonDivisor\u0060 evaluates the **GCD** of either two integers or a full list or array of them\r\nusing Euclid\u0027s algorithm. An extended version also returns how exactly the GCD can be composed from two\r\ninteger arguments.\r\n\r\n [lang=csharp]\r\n Euclid.GreatestCommonDivisor(10, 15, 45); // 5\r\n\r\n long x, y;\r\n Euclid.ExtendedGreatestCommonDivisor(45, 18, out x, out y) // 9\r\n // -\u003E x=1, y=-2, hence 9 == 1*45 \u002B -2*18\r\n\r\n\r\n#### Least Common Multiple\r\n\r\nClosely related to the GCD, \u0060LeastCommonMultiple\u0060 returns the **LCM** of two or more integers.\r\n\r\n [lang=csharp]\r\n Euclid.LeastCommonMultiple(3, 5, 6); // 30\r\n"},{"uri":"https://numerics.mathdotnet.com/Functions.html","title":"Special Functions\r\n","content":"Special Functions\r\n=================\r\n\r\nAll the following special functions are available in the static \u0060SpecialFunctions\u0060 class:\r\n\r\n\r\nFactorial\r\n---------\r\n\r\n* \u0060Factorial(x)\u0060\r\n\r\n$$$\r\nx \\mapsto x! = \\prod_{k=1}^{x} k = \\Gamma(x\u002B1)\r\n\r\nCode Sample:\r\n\r\n [lang=csharp]\r\n double x = SpecialFunctions.Factorial(14); // 87178291200.0\r\n double y = SpecialFunctions.Factorial(31); // 8.2228386541779224E\u002B33\r\n\r\n* \u0060FactorialLn(x)\u0060\r\n\r\n$$$\r\nx \\mapsto \\ln x! = \\ln\\Gamma(x\u002B1)\r\n\r\n* \u0060Binomial(n,k)\u0060\r\n\r\nBinomial Coefficient\r\n\r\n$$$\r\n\\binom{n}{k} = \\mathrm{C}_n^k = \\frac{n!}{k! (n-k)!}\r\n\r\n* \u0060BinomialLn(n,k)\u0060\r\n\r\n$$$\r\n\\ln \\binom{n}{k} = \\ln n! - \\ln k! - \\ln(n-k)!\r\n\r\n* \u0060Multinomial(n,k[])\u0060\r\n\r\nMultinomial Coefficient\r\n\r\n$$$\r\n\\binom{n}{k_1,k_2,\\dots,k_r} = \\frac{n!}{k_1! k_2! \\cdots k_r!} = \\frac{n!}{\\prod_{i=1}^{r}k_i!}\r\n\r\n\r\nExponential Integral\r\n--------------------\r\n\r\n* \u0060ExponentialIntegral(x,n)\u0060\r\n\r\nGeneralized Exponential Integral\r\n\r\n$$$\r\nE_n(x) = \\int_1^\\infty t^{-n} e^{-xt}\\,\\mathrm{d}t\r\n\r\n\r\nGamma functions\r\n---------------\r\n\r\n#### Gamma\r\n* \u0060Gamma(a)\u0060\r\n\r\n$$$\r\n\\Gamma(a) = \\int_0^\\infty t^{a-1} e^{-t}\\,\\mathrm{d}t\r\n\r\n* \u0060GammaLn(a)\u0060\r\n\r\n$$$\r\n\\ln\\Gamma(a)\r\n\r\n\r\n#### Incomplete Gamma\r\n* \u0060GammaLowerIncomplete(a,x)\u0060\r\n\r\nLower incomplete Gamma function, unregularized.\r\n\r\n$$$\r\n\\gamma(a,x) = \\int_0^x t^{a-1} e^{-t}\\,\\mathrm{d}t\r\n\r\n* \u0060GammaUpperIncomplete(a,x)\u0060\r\n\r\nUpper incomplete Gamma function, unregularized.\r\n\r\n$$$\r\n\\Gamma(a,x) = \\int_x^\\infty t^{a-1} e^{-t}\\,\\mathrm{d}t\r\n\r\n\r\n#### Regularized Gamma\r\n* \u0060GammaLowerRegularized(a,x)\u0060\r\n\r\nLower regularized incomplete Gamma function.\r\n\r\n$$$\r\n\\mathrm{P}(a,x) = \\frac{\\gamma(a,x)}{\\Gamma(a)}\r\n\r\n* \u0060GammaUpperRegularized(a,x)\u0060\r\n\r\nUpper regularized incomplete Gamma function.\r\n\r\n$$$\r\n\\mathrm{Q}(a,x) = \\frac{\\Gamma(a,x)}{\\Gamma(a)}\r\n\r\n* \u0060GammaLowerRegularizedInv(a, y)\u0060\r\n\r\nInverse $x$ of the lower regularized Gamma function, such that $\\mathrm{P}(a,x) = y$.\r\n\r\n$$$\r\n\\mathrm{P}^{-1}(a,y)\r\n\r\n\r\n#### Psi: Derivative of Logarithmic Gamma\r\n* \u0060DiGamma(x)\u0060\r\n\r\n$$$\r\n\\psi(x) = \\frac{\\mathrm{d}}{\\mathrm{d}x}\\ln\\Gamma(x)\r\n\r\n* \u0060DiGammaInv(p)\u0060\r\n\r\nInverse $x$ of the DiGamma function, such that $\\psi(x) = p$.\r\n\r\n$$$\r\n\\psi^{-1}(p)\r\n\r\n\r\nEuler Beta functions\r\n--------------------\r\n\r\n#### Euler Beta\r\n* \u0060Beta(a,b)\u0060\r\n\r\n$$$\r\n\\mathrm{B}(a,b) = \\int_0^1 t^{a-1} (1-t)^{b-1}\\,\\mathrm{d}t = \\frac{\\Gamma(a)\\Gamma(b)}{\\Gamma(a\u002Bb)}\r\n\r\n* \u0060BetaLn(a,b)\u0060\r\n\r\n$$$\r\n\\ln\\mathrm{B}(a,b) = \\ln\\Gamma(a) \u002B \\ln\\Gamma(b) - \\ln\\Gamma(a\u002Bb)\r\n\r\n\r\n#### Incomplete Beta\r\n* \u0060BetaIncomplete(a,b,x)\u0060\r\n\r\nLower incomplete Beta function (unregularized).\r\n\r\n$$$\r\n\\mathrm{B}_x(a,b) = \\int_0^x t^{a-1} (1-t)^{b-1}\\,\\mathrm{d}t\r\n\r\n\r\n#### Regularized Beta\r\n* \u0060BetaRegularized(a,b,x)\u0060\r\n\r\nLower incomplete regularized Beta function.\r\n\r\n$$$\r\n\\mathrm{I}_x(a,b) = \\frac{\\mathrm{B}(a,b,x)}{\\mathrm{B}(a,b)}\r\n\r\n\r\nError functions\r\n---------------\r\n\r\n#### Error Function\r\n* \u0060Erf(x)\u0060\r\n\r\n$$$\r\n\\mathrm{erf}(x) = \\frac{2}{\\sqrt{\\pi}}\\int_0^x e^{-t^2}\\,\\mathrm{d}t\r\n\r\n* \u0060ErfInv(z)\u0060\r\n\r\nInverse $x$ of the Error function, such that $\\mathrm{erf}(x) = z$.\r\n\r\n$$$\r\nz \\mapsto \\mathrm{erf}^{-1}(z)\r\n\r\n\r\n#### Complementary Error function.\r\n* \u0060Erfc(x)\u0060\r\n\r\n$$$\r\n\\mathrm{erfc}(x) = 1-\\mathrm{erf}(x) = \\frac{2}{\\sqrt{\\pi}}\\int_x^\\infty e^{-t^2}\\,\\mathrm{d}t\r\n\r\n* \u0060ErfcInv(z)\u0060\r\n\r\nInverse $x$ of the complementary Error function, such that $\\mathrm{erfc}(x) = z$.\r\n\r\n$$$\r\nz \\mapsto \\mathrm{erfc}^{-1}(z)\r\n\r\nCode Sample:\r\n\r\n [lang=csharp]\r\n double erf = SpecialFunctions.Erf(0.9); // 0.7969082124\r\n\r\n\r\nSigmoid: Logistic function\r\n--------------------------\r\n\r\n* \u0060Logistic(x)\u0060\r\n\r\n$$$\r\nx \\mapsto \\frac{1}{1\u002Be^{-x}}\r\n\r\n* \u0060Logit(y)\u0060\r\n\r\nInverse of the Logistic function, for $y$ between 0 and 1 (where the function is real-valued).\r\n\r\n$$$\r\ny \\mapsto \\ln \\frac{y}{1-y}\r\n\r\n\r\nHarmonic Numbers\r\n----------------\r\n\r\n* \u0060Harmonic(t)\u0060\r\n\r\nThe n-th Harmonic number is the sum of the reciprocals of the first n natural numbers.\r\nWith $\\gamma$ as the Euler-Mascheroni constant and the DiGamma function:\r\n\r\n$$$\r\n\\mathrm{H}_n = \\sum_{k=1}^{n}\\frac{1}{k} = \\gamma - \\psi(n\u002B1)\r\n\r\n* \u0060GeneralHarmonic(n, m)\u0060\r\n\r\nGeneralized harmonic number of order n of m.\r\n\r\n$$$\r\n\\mathrm{H}_{n,m} = \\sum_{k=1}^{n}\\frac{1}{k^m}\r\n\r\n\r\nBessel and Struve Functions\r\n---------------------------\r\n\r\n#### Bessel functions\r\n\r\nBessel functions are canonical solutions $y(x)$ of Bessel\u0027s differential equation\r\n\r\n$$$\r\nx^2\\frac{\\mathrm{d}^2y}{\\mathrm{d}x^2}\u002Bx\\frac{\\mathrm{d}y}{\\mathrm{d}x}\u002B(x^2-\\alpha^2)y = 0\r\n\r\n#### Modified Bessel functions\r\n\r\nModified Bessel\u0027s equation:\r\n\r\n$$$\r\nx^2\\frac{\\mathrm{d}^2y}{\\mathrm{d}x^2}\u002Bx\\frac{\\mathrm{d}y}{\\mathrm{d}x}-(x^2\u002B\\alpha^2)y = 0\r\n\r\nModified Bessel functions:\r\n\r\n$$$\r\n\\begin{align}\r\n\\mathrm{I}_\\alpha(x) \u0026= \\imath^{-\\alpha}\\mathrm{J}_\\alpha(\\imath x) = \\sum_{m=0}^\\infty \\frac{1}{m!\\Gamma(m\u002B\\alpha\u002B1)}\\left(\\frac{x}{2}\\right)^{2m\u002B\\alpha} \\\\\r\n\\mathrm{K}_\\alpha(x) \u0026= \\frac{\\pi}{2} \\frac{\\mathrm{I}_{-\\alpha}(x)-\\mathrm{I}_\\alpha(x)}{\\sin(\\alpha\\pi)}\r\n\\end{align}\r\n\r\n* \u0060BesselI0(x)\u0060\r\n\r\nModified or hyperbolic Bessel function of the first kind, order 0.\r\n\r\n$$$\r\nx \\mapsto \\mathrm{I}_0(x)\r\n\r\n* \u0060BesselI1(x)\u0060\r\n\r\nModified or hyperbolic Bessel function of the first kind, order 1.\r\n\r\n$$$\r\nx \\mapsto \\mathrm{I}_1(x)\r\n\r\n* \u0060BesselK0(x)\u0060\r\n\r\nModified or hyperbolic Bessel function of the second kind, order 0.\r\n\r\n$$$\r\nx \\mapsto \\mathrm{K}_0(x)\r\n\r\n* \u0060BesselK0e(x)\u0060\r\n\r\nExponentionally scaled modified Bessel function of the second kind, order 0.\r\n\r\n$$$\r\nx \\mapsto e^x\\mathrm{K}_0(x)\r\n\r\n* \u0060BesselK1(x)\u0060\r\n\r\nModified or hyperbolic Bessel function of the second kind, order 1.\r\n\r\n$$$\r\nx \\mapsto \\mathrm{K}_1(x)\r\n\r\n* \u0060BesselK1e(x)\u0060\r\n\r\nExponentially scaled modified Bessel function of the second kind, order 1.\r\n\r\n$$$\r\nx \\mapsto e^x\\mathrm{K}_1(x)\r\n\r\n#### Struve functions\r\n\r\nStruve functions are solutions $y(x)$ of the non-homogeneous Bessel\u0027s differential equation\r\n\r\n$$$\r\nx^2\\frac{\\mathrm{d}^2y}{\\mathrm{d}x^2}\u002Bx\\frac{\\mathrm{d}y}{\\mathrm{d}x}\u002B(x^2-\\alpha^2)y = \\frac{4(\\frac{x}{2})^{\\alpha\u002B1}}{\\sqrt{\\pi}\\Gamma(\\alpha\u002B\\frac{1}{2})}\r\n\r\n\r\n#### Modified Struve functions\r\n\r\nModified equation:\r\n\r\n$$$\r\nx^2\\frac{\\mathrm{d}^2y}{\\mathrm{d}x^2}\u002Bx\\frac{\\mathrm{d}y}{\\mathrm{d}x}-(x^2\u002B\\alpha^2)y = \\frac{4(\\frac{x}{2})^{\\alpha\u002B1}}{\\sqrt{\\pi}\\Gamma(\\alpha\u002B\\frac{1}{2})}\r\n\r\nModified Struve functions:\r\n\r\n$$$\r\n\\mathrm{L}_\\alpha(x) = \\left(\\frac{x}{2}\\right)^{\\alpha\u002B1}\\sum_{k=0}^\\infty \\frac{1}{\\Gamma(\\frac{3}{2}\u002Bk)\\Gamma(\\frac{3}{2}\u002Bk\u002B\\alpha)}\\left(\\frac{x}{2}\\right)^{2k}\r\n\r\n* \u0060StruveL0(x)\u0060\r\n\r\nModified Struve function of order 0.\r\n\r\n$$$\r\nx \\mapsto \\mathrm{L}_0(x)\r\n\r\n* \u0060StruveL1(x)\u0060\r\n\r\nModified Struve function of order 1.\r\n\r\n$$$\r\nx \\mapsto \\mathrm{L}_1(x)\r\n\r\n\r\n#### Misc\r\n\r\n* \u0060BesselI0MStruveL0(x)\u0060\r\n\r\nDifference between the Bessel $I_0$ and the Struve $L_0$ functions.\r\n\r\n$$$\r\nx \\mapsto I_0(x) - L_0(x)\r\n\r\n* \u0060BesselI1MStruveL1(x)\u0060\r\n\r\nDifference between the Bessel $I_1$ and the Struve $L_1$ functions.\r\n\r\n$$$\r\nx \\mapsto I_1(x) - L_1(x)\r\n\r\n\r\nNumeric Stability\r\n-----------------\r\n\r\n* \u0060ExponentialMinusOne(power)\u0060\r\n\r\n$\\exp x-1$ is a typical case where a subtraction can be fatal for accuracy.\r\nFor example, at $10^{-13}$ the naive expression is 0.08% off, at $10^{-15}$\r\nroughly 11% and at $10^{-18}$ it just returns 0.\r\n\r\n$$$\r\nx \\mapsto e^x - 1\r\n\r\n* \u0060Hypotenuse(a, b)\u0060\r\n\r\n$$$\r\n(a,b) \\mapsto \\sqrt{a^2 \u002B b^2}\r\n\r\n\r\nTrigonometry\r\n------------\r\n\r\nThe \u0060Trig\u0060 class provides the complete set of fundamental trigonometric functions\r\nfor both real and complex arguments.\r\n\r\n* **Trigonometric**: Sin, Cos, Tan, Cot, Sec, Csc\r\n* **Trigonometric Inverse**: Asin, Acos, Atan, Acot, Asec, Acsc\r\n* **Hyperbolic**: Sinh, Cosh, Tanh, Coth, Sech, Csch\r\n* **Hyperbolic Area**: Asinh, Acosh, Atanh, Acoth, Asech, Acsch\r\n* **Sinc**: Normalized sinc function $x \\mapsto \\frac{\\sin\\pi x}{\\pi x}$\r\n* Conversion routines between radian, degree and grad.\r\n"},{"uri":"https://numerics.mathdotnet.com/Generate.html","title":"Generating Data\r\n","content":" [hide]\r\n #I \u0022../../out/lib/net40\u0022\r\n #r \u0022MathNet.Numerics.dll\u0022\r\n #r \u0022MathNet.Numerics.FSharp.dll\u0022\r\n open System.Numerics\r\n open MathNet.Numerics\r\n open MathNet.Numerics.Statistics\r\n let a = [| 2.0; 4.0; 3.0; 6.0 |]\r\n\r\nGenerating Data\r\n===============\r\n\r\nNumerics is all about analyzing and manipulating numeric data. But unless you can read in data from an external\r\nfile, source or e.g. with the excellent [F# Type Providers](https://fsharp.github.io/FSharp.Data/),\r\nyou may need to generate synthetic or random data locally, or transform existing data into a new form.\r\nThe \u0060Generate\u0060 class can help you in all these scenarios with a set of static functions generating either\r\nan array or an IEnumerable sequence.\r\n\r\nThere is some overlap with LINQ, in case of F# also with some integrated language features and its fundamental types.\r\nThis is intended for simplicity and consistency between array and sequence operations, as LINQ only supports sequences.\r\n\r\n\r\nLinear Range\r\n------------\r\n\r\nGenerates a linearly spaced array within the inclusive interval between start and stop,\r\nand either a provided step or a step of 1.0. Linear range is equivalent to the\r\nsingle colon \u0060:\u0060 and double colon \u0060::\u0060 operators in MATLAB.\r\n\r\nF# has built in linear range support in array comprehensions with the colon operator:\r\n\r\n [lang=fsharp]\r\n [ 10.0 .. 2.0 .. 15.0 ]\r\n // [fsi:val it : float list = [10.0; 12.0; 14.0] ]\r\n [ for x in 10.0 .. 2.0 .. 15.0 -\u003E sin x ]\r\n // [fsi:val it : float list = [-0.5440211109; -0.536572918; 0.9906073557] ]\r\n\r\nIn C# you can get the same result with \u0060LinearRange\u0060:\r\n\r\n [lang=csharp]\r\n Generate.LinearRange(10, 2, 15); // returns array { 10.0, 12.0, 14.0 }\r\n Generate.LinearRangeMap(10, 2, 15, Math.Sin); // applies sin(x) to each value\r\n\r\nMost of the routines in the \u0060Generate\u0060 class have variants with a \u0060Map\u0060 suffix.\r\nInstead of returning an array with the generated numbers, these routines instead\r\napply the generated numbers to a custom function and return an array with the results.\r\nSimilarly, some routines have variants with a \u0060Sequence\u0060 suffix that return\r\nlazy enumerable sequences instead of arrays.\r\n\r\n\r\nLinear-Spaced and Log-Spaced\r\n----------------------------\r\n\r\nGenerates a linearly or log-spaced array within an interval, but other than linear range\r\nwhere the step is provided, here we instead provide the number of values we want.\r\nThis is equivalent to the linspace and logspace operators in MATLAB.\r\n\r\n [lang=csharp]\r\n Generate.LinearSpaced(11, 0.0, 1.0); // returns array { 0.0, 0.1, 0.2, .., 1.0 }\r\n Generate.LinearSpacedMap(15, 0.0, Math.Pi, Math.Sin); // applies sin(x) to each value\r\n\r\nIn F# you can also use:\r\n\r\n [lang=fsharp]\r\n Generate.linearSpacedMap 15 0.0 Math.PI sin\r\n // [fsi:val it : float [] = ]\r\n // [fsi: [|0.0; 0.222520934; 0.4338837391; 0.6234898019; 0.7818314825; 0.9009688679; ]\r\n // [fsi: 0.9749279122; 1.0; 0.9749279122; 0.9009688679; 0.7818314825; 0.6234898019; ]\r\n // [fsi: 0.4338837391; 0.222520934; 1.224606354e-16|] ]\r\n\r\n\u0060LogSpaced\u0060 works the same way but instead of the values $10^x$ it spaces the decade exponents $x$ linearly\r\nbetween the provided two exponents.\r\n\r\n [lang=csharp]\r\n Generate.LogSpaced(4,0,3); // returns array { 1, 10, 100, 1000 }\r\n\r\n\r\nKronecker Delta Impulse\r\n-----------------------\r\n\r\nThe Kronecker delta $\\delta[n]$ is a fundamental signal in time-discrete signal processing,\r\noften referred to as *unit impulse*. When applied to a system, the resulting output is the system\u0027s *impulse response*.\r\nIt is closely related to the Dirac delta impulse function $\\delta(x)$ in continuous signal processing.\r\n\r\n$$$\r\n\\delta[n] = \\begin{cases} 0 \u0026\\mbox{if } n \\ne 0 \\\\ 1 \u0026 \\mbox{if } n = 0\\end{cases}\r\n\r\nThe \u0060Impulse\u0060 routine generates a Kronecker delta impulse, but also accepts a sample delay\r\nparameter $d$ and amplitude $A$ such that the resulting generated signal is\r\n\r\n$$$\r\ns[n] = A\\cdot\\delta[n-d] = \\begin{cases} 0 \u0026\\mbox{if } n \\ne d \\\\ A \u0026 \\mbox{if } n = d\\end{cases}\r\n\r\nThere is also a periodic version in \u0060PeriodicImpulse\u0060 which accepts an additional \u0060period\u0060 parameter.\r\n\r\n [lang=fsharp]\r\n Generate.Impulse(8, 2.0, 3)\r\n // [fsi:val it : float [] = [|0.0; 0.0; 0.0; 2.0; 0.0; 0.0; 0.0; 0.0|] ]\r\n\r\n Generate.PeriodicImpulse(8, 3, 10.0, 1)\r\n // [fsi:val it : float [] = [|0.0; 10.0; 0.0; 0.0; 10.0; 0.0; 0.0; 10.0|] ]\r\n\r\n\r\nHeaviside Step\r\n--------------\r\n\r\nAnother fundamental signal in signal processing, the Heaviside step function $H[n]$\r\nis the integral of the Dirac delta impulse and represents a signal that switches on\r\nat a specified time and then stays on indefinitely. In discrete time:\r\n\r\n$$$\r\nH[n] = \\begin{cases} 0 \u0026\\mbox{if } n \u003C 0 \\\\ 1 \u0026 \\mbox{if } n \\ge 0\\end{cases}\r\n\r\nThe \u0060Step\u0060 routines generates a Heaviside step, but just like the Kronecker Delta impulse\r\n also accepts a sample delay parameter $d$ and amplitude $A$ such that the resulting generated signal is\r\n\r\n$$$\r\ns[n] = A\\cdot H[n-d] = \\begin{cases} 0 \u0026\\mbox{if } n \u003C d \\\\ A \u0026 \\mbox{if } n \\ge d\\end{cases}\r\n\r\n [lang=fsharp]\r\n Generate.Step(8, 2.0, 3)\r\n // [fsi:val it : float [] = [|0.0; 0.0; 0.0; 2.0; 2.0; 2.0; 2.0; 2.0|] ]\r\n\r\n\r\nPeriodic Sawtooth\r\n-----------------\r\n\r\nGenerates an array of the given length with a periodic upper forward sawtooth signal,\r\ni.e. a line starting at zero up to some amplitude $A$, then drop back to zero instantly and start afresh.\r\nThe sawtooth can be used to turn any arbitrary function defined over the interval $[0,A)$ into a\r\nperiodic function by repeating it continuously.\r\n\r\nMathematically, the sawtooth can be described using the fractional part function\r\n$\\mathrm{frac}(x) \\equiv x - \\lfloor x \\rfloor$, frequency $\\nu$ and phase $\\theta$ as\r\n\r\n$$$\r\ns(x) = A\\cdot\\mathrm{frac}\\left(x\\nu\u002B\\frac{\\theta}{A}\\right)\r\n\r\nIn a trigonometric interpretation the signal represents the angular position $\\alpha$ of a point moving endlessly\r\naround a circle with radius $\\frac{A}{2\\pi}$ (and thus circumference $A$) in constant speed,\r\nnormalized to strictly $0\\le\\alpha \u003C A$.\r\n\r\n\u0060Generate.Periodic(length,samplingRate,frequency,amplitude,phase,delay)\u0060\r\n\r\n* **Sampling Rate**: Number of samples $r$ per time unit. If the time unit is 1s, the sampling rate has unit Hz.\r\n* **Frequency**: Frequency $\\nu$ of the signal, in sawtooth-periods per time unit. If the time unit is 1s, the frequency has unit Hz.\r\n For a desired number of samples $n$ per sawtooth-period and sampling rate $r$ choose $\\nu=\\frac{r}{n}$.\r\n* **Amplitude**: The theoretical maximum value $A$, which is never reached and logically equivalent to zero.\r\n The circumference of the circle. Typically $1$ or $2\\pi$.\r\n* **Phase**: Optional initial value or phase offset. Contributes to $\\theta$.\r\n* **Delay**: Optional initial delay, in samples. Contributes to $\\theta$.\r\n\r\nThe equivalent map function accepts a custom map lambda as second argument after the length:\r\n\r\n [lang=fsharp]\r\n Generate.periodicMap 15 ((\u002B) 100.0) 1000.0 100.0 10.0 0.0 0\r\n // [fsi:val it : float [] = ]\r\n // [fsi: [|100.0; 101.0; 102.0; 103.0; 104.0; 105.0; 106.0; 107.0; 108.0; 109.0; ]\r\n // [fsi: 100.0; 101.0; 102.0; 103.0; 104.0|] ]\r\n\r\n\r\nSinusoidal\r\n----------\r\n\r\nGenerates a Sine wave array of the given length. This is equivalent to applying a scaled\r\ntrigonometric Sine function to a periodic sawtooth of amplitude $2\\pi$.\r\n\r\n$$$\r\ns(x) = A\\cdot\\sin(2\\pi\\nu x \u002B \\theta)\r\n\r\n\u0060Generate.Sinusoidal(length,samplingRate,frequency,amplitude,mean,phase,delay)\u0060\r\n\r\n [lang=csharp]\r\n Generate.Sinusoidal(15, 1000.0, 100.0, 10.0);\r\n // returns array { 0, 5.9, 9.5, 9.5, 5.9, 0, -5.9, ... }\r\n\r\n\r\nRandom\r\n------\r\n\r\nGenerate random sequences by sampling from a random distribution.\r\n\r\n\r\n#### Uniform Distribution\r\n\r\nGenerate sample sequences distributed uniformly between 0 and 1.\r\n\r\n [lang=csharp]\r\n Generate.Uniform(100); // e.g. 0.867421787170424, 0.236744313145403, ... \r\n\r\nUniform supports mapping to functions with not only one but also two uniform variables\r\nas arguments, with \u0060UniformMap\u0060 and \u0060UniformMap2\u0060. As usual, lazy sequences can be\r\ngenerated using the variants with the \u0060Sequence\u0060 suffix, e.g. \u0060UniformMap2Sequence\u0060.\r\n\r\n\r\n#### Non-Uniform Distributions\r\n\r\nInstead of uniform we can also sample from other distributions.\r\n\r\n* \u0060Normal\u0060 - sample an array or sequence form a normal distribution\r\n* \u0060Standard\u0060 - sample an array or sequence form a standard distribution\r\n\r\nIn addition, the \u0060Random\u0060 functions accept a custom distribution instance to sample\r\nfrom. See the section about random numbers and probability distributions for details.\r\n\r\n\r\nMap\r\n---\r\n\r\nGenerates a new array or sequence where each new values is the result of applying the provided function\r\nthe the corresponding value in the input data.\r\n\r\n [lang=csharp]\r\n var a = new double[] { 2.0, 4.0, 3.0, 6.0 };\r\n Generate.Map(a, x =\u003E x \u002B 1.0); // returns array { 3.0, 5.0, 4.0, 7.0 }\r\n\r\nIn F# you\u0027d typically use the Array module to the same effect (and should continue to do so):\r\n\r\n [lang=fsharp]\r\n Array.map ((\u002B) 1.0) a\r\n // [fsi:val it : float [] = [|3.0; 5.0; 4.0; 7.0|] ]\r\n\r\n...but no equivalent operation is available in the .NET base class libraries (BCL) for C#.\r\nYou can use LINQ, but that operates on sequences instead of arrays:\r\n\r\n [lang=csharp]\r\n a.Select(x =\u003E x \u002B 1.0).ToArray();\r\n\r\nSimilarly, with \u0060Map2\u0060 you can also map a function accepting two inputs to two input arrays:\r\n\r\n [lang=fsharp]\r\n let b = [| 1.0; -1.0; 2.0; -2.0 |]\r\n Generate.Map2(a, b, fun x y -\u003E x \u002B y)\r\n // [fsi:val it : float [] = [|3.0; 3.0; 5.0; 4.0|] ]\r\n\r\nTypical F# equivalent:\r\n\r\n [lang=fsharp]\r\n Array.map2 (\u002B) a b\r\n // [fsi:val it : float [] = [|3.0; 3.0; 5.0; 4.0|] ]\r\n\r\nAnd in C# with LINQ:\r\n\r\n [lang=csharp]\r\n a.Zip(b, (x, y) =\u003E x \u002B y).ToArray();\r\n"},{"uri":"https://numerics.mathdotnet.com/IFsharpNotebook.html","title":"IF# Notebook\r\n","content":" [hide]\r\n #I \u0022../../out/lib/net40\u0022\r\n #r \u0022MathNet.Numerics.dll\u0022\r\n #r \u0022MathNet.Numerics.FSharp.dll\u0022\r\n open System.Numerics\r\n open MathNet.Numerics\r\n open MathNet.Numerics.LinearAlgebra\r\n\r\nIF# Notebook\r\n============\r\n\r\n[iPython](https://ipython.org/) provides a rich browser-based interactive notebook with support for code, text, mathematical expressions,\r\ninline plots and other rich media. [IfSharp](https://github.com/BayardRock/IfSharp), developed by Bayard Rock, is an F# profile\r\nfor iPython with IntelliSense and embedded FSharp.Charting. Thanks to its NuGet support it can load other packages like Math.NET Numerics on demand.\r\n\r\n![Screenshot](img/IfSharp-GenerateIS.png)\r\n\r\n\r\nInstalling IF# Notebook\r\n-----------------------\r\n\r\nFollow the instructions at [IfSharp/Installation](https://bayardrock.github.io/IfSharp/installation.html).\r\n\r\nEssentially:\r\n\r\n1. Install [Anaconda](https://continuum.io/downloads)\r\n2. In a shell, run\r\n\r\n conda update conda\r\n conda update ipython\r\n\r\n3. Install [IfSharp](https://github.com/BayardRock/IfSharp/releases).\r\n\r\n\r\nDisplay Printers for Matrices and Vectors\r\n-----------------------------------------\r\n\r\nBy itself IfSharp does not know how to display matrices and vectors in a nice way, but we can tell it how to do so by providing our own display printers for them.\r\nSince v3.3 the Math.NET Numerics F# package includes a script \u0060MathNet.Numerics.IfSharp.fsx\u0060 to do so.\r\nUnfortunately loading this script requires the exact version in the path - if you know a way to avoid this please let us know.\r\n\r\n![Screenshot](img/IfSharp-MatrixVector.png)\r\n\r\nAlternatively you can also use the code below and adapt it to your needs, e.g. if you want it to show more rows.\r\n\r\n [lang=fsharp]\r\n open MathNet.Numerics.LinearAlgebra\r\n\r\n let inline (|Float|_|) (v:obj) =\r\n if v :? float then Some(v :?\u003E float) else None\r\n let inline (|Float32|_|) (v:obj) =\r\n if v :? float32 then Some(v :?\u003E float32) else None\r\n let inline (|PositiveInfinity|_|) (v: ^T) =\r\n if (^T : (static member IsPositiveInfinity: \u0027T -\u003E bool) (v))\r\n then Some PositiveInfinity else None\r\n let inline (|NegativeInfinity|_|) (v: ^T) =\r\n if (^T : (static member IsNegativeInfinity: \u0027T -\u003E bool) (v))\r\n then Some NegativeInfinity else None\r\n let inline (|NaN|_|) (v: ^T) =\r\n if (^T : (static member IsNaN: \u0027T -\u003E bool) (v))\r\n then Some NaN else None\r\n\r\n let inline formatMathValue (floatFormat:string) = function\r\n | PositiveInfinity -\u003E \u0022\\\\infty\u0022\r\n | NegativeInfinity -\u003E \u0022-\\\\infty\u0022\r\n | NaN -\u003E \u0022\\\\times\u0022\r\n | Float v -\u003E v.ToString(floatFormat)\r\n | Float32 v -\u003E v.ToString(floatFormat)\r\n | v -\u003E v.ToString()\r\n\r\n let inline formatMatrix (matrix: Matrix\u003C\u0027T\u003E) =\r\n String.concat Environment.NewLine\r\n [ \u0022\\\\begin{bmatrix}\u0022\r\n matrix.ToMatrixString(10,4,7,2,\u0022\\\\cdots\u0022,\u0022\\\\vdots\u0022,\u0022\\\\ddots\u0022,\r\n \u0022 \u0026 \u0022, \u0022\\\\\\\\ \u0022 \u002B Environment.NewLine, (fun x -\u003E formatMathValue \u0022G4\u0022 x))\r\n \u0022\\\\end{bmatrix}\u0022 ]\r\n\r\n let inline formatVector (vector: Vector\u003C\u0027T\u003E) =\r\n String.concat Environment.NewLine\r\n [ \u0022\\\\begin{bmatrix}\u0022\r\n vector.ToVectorString(12, 80, \u0022\\\\vdots\u0022, \u0022 \u0026 \u0022, \u0022\\\\\\\\ \u0022 \u002B Environment.NewLine,\r\n (fun x -\u003E formatMathValue \u0022G4\u0022 x))\r\n \u0022\\\\end{bmatrix}\u0022 ]\r\n\r\n App.AddDisplayPrinter (fun (x:Matrix\u003Cfloat\u003E) -\u003E\r\n { ContentType = \u0022text/latex\u0022; Data = formatMatrix x })\r\n App.AddDisplayPrinter (fun (x:Matrix\u003Cfloat32\u003E) -\u003E\r\n { ContentType = \u0022text/latex\u0022; Data = formatMatrix x })\r\n App.AddDisplayPrinter (fun (x:Vector\u003Cfloat\u003E) -\u003E\r\n { ContentType = \u0022text/latex\u0022; Data = formatVector x })\r\n App.AddDisplayPrinter (fun (x:Vector\u003Cfloat32\u003E) -\u003E\r\n { ContentType = \u0022text/latex\u0022; Data = formatVector x })\r\n"},{"uri":"https://numerics.mathdotnet.com/index.html","title":"Math.NET Numerics\r\n","content":"Math.NET Numerics\r\n=================\r\n\r\nMath.NET Numerics aims to provide methods and algorithms for numerical computations\r\nin science, engineering and every day use. Covered topics include special functions,\r\nlinear algebra, probability models, random numbers, interpolation, integration,\r\nregression, optimization problems and more.\r\n\r\nMath.NET Numerics is part of the [Math.NET initiative](https://www.mathdotnet.com/)\r\nand is the result of merging dnAnalytics with Math.NET Iridium, replacing both.\r\nAvailable for free under the [MIT License](License.html).\r\nIt targets Microsoft .NET 5.0, .NET 4.6.1 and higher, and .NET Standard 2.0\r\nand higher. In addition to a purely managed implementation it also supports\r\nnative hardware optimization. See [Platform Support](Compatibility.html) for full details.\r\n\r\nNuGet Packages\r\n--------------\r\n\r\n- [**MathNet.Numerics**](https://www.nuget.org/packages/MathNet.Numerics/) - core package\r\n- [**MathNet.Numerics.FSharp**](https://www.nuget.org/packages/MathNet.Numerics.FSharp/) - optional extensions for a better experience when using F#.\r\n\r\nSee [NuGet \u0026 Binaries](Packages.html) for a complete list of our NuGet packages,\r\nZip files and the release archive.\r\n\r\n [hide]\r\n #I \u0022../../out/lib/net40\u0022\r\n #r \u0022MathNet.Numerics.dll\u0022\r\n #r \u0022MathNet.Numerics.FSharp.dll\u0022\r\n\r\nUsing Math.NET Numerics with C#\r\n-------------------------------\r\n\r\nBeing written in it, Math.NET Numerics works very well with C# and related .Net languages.\r\nWhen using Visual Studio or another IDE with built-in NuGet support, you can get started\r\nquickly by adding a reference to the \u0060MathNet.Numerics\u0060 NuGet package. Alternatively you can grab\r\nthat package with the command line tool with \u0060nuget.exe install MathNet.Numerics -Pre\u0060\r\nor simply download the Zip package.\r\n\r\nlet\u0027s say we have a matrix $\\mathrm{A}$ and want to find an orthonormal basis of the kernel or null-space\r\nof that matrix, such that $\\mathrm{A}x = 0$ for all $x$ in that subspace.\r\n\r\n [lang=csharp]\r\n using MathNet.Numerics.LinearAlgebra;\r\n using MathNet.Numerics.LinearAlgebra.Double;\r\n\r\n Matrix\u003Cdouble\u003E A = DenseMatrix.OfArray(new double[,] {\r\n {1,1,1,1},\r\n {1,2,3,4},\r\n {4,3,2,1}});\r\n Vector\u003Cdouble\u003E[] nullspace = A.Kernel();\r\n\r\n // verify: the following should be approximately (0,0,0)\r\n (A * (2*nullspace[0] - 3*nullspace[1]))\r\n\r\n\r\nF# and F# Interactive\r\n---------------------\r\n\r\nEven though the core of Math.NET Numerics is written in C#, it aims to support F#\r\njust as well. In order to achieve this we recommend to reference the \u0060MathNet.Numerics.FSharp\u0060\r\npackage in addition to \u0060MathNet.Numerics\u0060, which adds a few modules to make it more\r\nidiomatic and includes arbitrary precision types (BigInteger, BigRational).\r\n\r\n [lang=fsharp]\r\n open MathNet.Numerics.LinearAlgebra\r\n let m = matrix [[ 1.0; 2.0 ]\r\n [ 3.0; 4.0 ]]\r\n let m\u0027 = m.Inverse()\r\n\r\nIt also works well in the interactive F# environment (REPL) which can be launched with\r\n\u0060fsharpi\u0060 on all platforms (including Linux). As a start let\u0027s enter the following lines\r\ninto F# interactive. Append \u0060;;\u0060 to the end of a line to run all code up to there\r\nimmediately and print the result to the output. Use the tab key for auto-completion or \u0060#help;;\u0060 for help.\r\nFor convenience our F# packages include a small script that sets everything up properly:\r\n\r\n [lang=fsharp]\r\n #load \u0022../packages/MathNet.Numerics.FSharp/MathNet.Numerics.fsx\u0022\r\n\r\n open MathNet.Numerics\r\n SpecialFunctions.Gamma(0.5)\r\n\r\n open MathNet.Numerics.LinearAlgebra\r\n let m : Matrix\u003Cfloat\u003E = DenseMatrix.randomStandard 50 50\r\n (m * m.Transpose()).Determinant()\r\n\r\n\r\nVisual Basic\r\n------------\r\n\r\nLet\u0027s use Visual Basic to find the polynomial roots $x$ such that $2x^2 - 2x - 2 = 0$\r\nnumerically. We already know there are two roots, one between -2 and 0, the other between 0 and 2:\r\n\r\n [lang=visualbasic]\r\n Imports MathNet.Numerics.RootFinding\r\n\r\n Dim f As Func(Of Double, Double) = Function(x) 2*x^2 - 2*x - 2\r\n\r\n Bisection.FindRoot(f, 0, 2) \u0027 returns 1.61803398874989\r\n Bisection.FindRoot(f, -2, 0) \u0027 returns -0.618033988749895\r\n\r\n \u0027 Alternative to directly compute the roots for this special case:\r\n FindRoots.Quadratic(-2, -2, 2)\r\n\r\n\r\nLinux with Mono\r\n---------------\r\n\r\nYou need a recent version of Mono in order to use Math.NET Numerics on anything other than Windows.\r\nLuckily there has been great progress lately to make both Mono and F# available as proper Debian packages.\r\nIn Debian *testing* and Ubuntu *14.04 (trusty/universe)* you can install both of them with APT:\r\n\r\n [lang=sh]\r\n sudo apt-get update\r\n sudo apt-get install mono-complete\r\n sudo apt-get install fsharp\r\n\r\nIf you don\u0027t have NuGet yet:\r\n\r\n [lang=sh]\r\n sudo mozroots --import --sync\r\n curl -L https://nuget.org/nuget.exe -o nuget.exe\r\n\r\nThen you can use NuGet to fetch the latest binaries in your working directory.\r\nThe \u0060-Pre\u0060 argument causes it to include pre-releases, omit it if you want stable releases only.\r\n\r\n [lang=sh]\r\n mono nuget.exe install MathNet.Numerics -Pre -OutputDirectory packages\r\n # or if you intend to use F#:\r\n mono nuget.exe install MathNet.Numerics.FSharp -Pre -OutputDirectory packages\r\n\r\nIn practice you\u0027d probably use the Monodevelop IDE instead which can take care of fetching and updating\r\nNuGet packages and maintain assembly references. But for completeness let\u0027s use the compiler directly this time.\r\nLet\u0027s create a C# file \u0060Start.cs\u0060:\r\n\r\n [lang=csharp]\r\n using System;\r\n using MathNet.Numerics;\r\n using MathNet.Numerics.LinearAlgebra;\r\n\r\n class Program\r\n {\r\n static void Main(string[] args)\r\n {\r\n // Evaluate a special function\r\n Console.WriteLine(SpecialFunctions.Erf(0.5));\r\n\r\n // Solve a random linear equation system with 500 unknowns\r\n var m = Matrix\u003Cdouble\u003E.Build.Random(500, 500);\r\n var v = Vector\u003Cdouble\u003E.Build.Random(500);\r\n var y = m.Solve(v);\r\n Console.WriteLine(y);\r\n }\r\n }\r\n\r\nCompile and run:\r\n\r\n [lang=sh]\r\n # single line:\r\n mcs -optimize -lib:packages/MathNet.Numerics.3.0.0-alpha8/lib/net40/\r\n -r:MathNet.Numerics.dll Start.cs -out:Start\r\n # launch:\r\n mono Start\r\n\r\nWhich will print something like the following to the output:\r\n\r\n [lang=text]\r\n 0.520499877813047\r\n DenseVector 500-Double\r\n -0.181414 -1.25024 -0.607136 1.12975 -3.31201 0.344146\r\n 0.934095 -2.96364 1.84499 1.20752 0.753055 1.56942\r\n 0.472414 6.10418 -0.359401 0.613927 -0.140105 2.6079\r\n 0.163564 -3.04402 -0.350791 2.37228 -1.65218 -0.84056\r\n 1.51311 -2.17326 -0.220243 -0.0368934 -0.970052 0.580543\r\n 0.755483 -1.01755 -0.904162 -1.21824 -2.24888 1.42923\r\n -0.971345 -3.16723 -0.822723 1.85148 -1.12235 -0.547885\r\n -2.01044 4.06481 -0.128382 0.51167 -1.70276 ...\r\n\r\nSee [Intel MKL](MKL.html) for details how to use native providers on Linux.\r\n"},{"uri":"https://numerics.mathdotnet.com/IntegralTransforms.html","title":"Fourier and related linear integral transforms\r\n","content":" [hide]\r\n #I \u0022../../out/lib/net40\u0022\r\n #r \u0022MathNet.Numerics.dll\u0022\r\n #r \u0022MathNet.Numerics.FSharp.dll\u0022\r\n open System.Numerics\r\n open MathNet.Numerics\r\n open MathNet.Numerics.IntegralTransforms\r\n\r\nFourier and related linear integral transforms\r\n==============================================\r\n\r\nMath.NET Numerics currently supports two linear integral transforms: The discrete Fourier\r\ntransform and the discrete Hartley transform. Both are strongly localized in the frequency\r\nspectrum, but while the Fourier transform operates on complex values, the Hartley transform\r\noperates on real values only.\r\n\r\nThe transforms implement a separate forward and inverse transform method.\r\nHow the forward and inverse methods are related to each other and what exact definition\r\nis to be used can be specified by an additional _options_ parameter.\r\n\r\n\r\nFourier Space: Discrete Fourier Transform and FFT\r\n-------------------------------------------------\r\n\r\nWikipedia has an extensive [article on the discrete Fourier transform (DFT)](https://en.wikipedia.org/wiki/Discrete_Fourier_transform).\r\nWe provide implementations of the following algorithms:\r\n\r\n* *Naive Discrete Fourier Transform (DFT):* Out-place transform for arbitrary vector lengths. Mainly intended for verifying faster algorithms: _[NaiveForward](https://numerics.mathdotnet.com/api/MathNet.Numerics.IntegralTransforms/Fourier.htm#NaiveForward)_, _[NaiveInverse](https://numerics.mathdotnet.com/api/MathNet.Numerics.IntegralTransforms/Fourier.htm#NaiveInverse)_\r\n\r\n* *Radix-2 Fast Fourier Transform (FFT):* In-place fast Fourier transform for vectors with a power-of-two length (Radix-2): _[Radix2Forward](https://numerics.mathdotnet.com/api/MathNet.Numerics.IntegralTransforms/Fourier.htm#Radix2Forward)_, _[url:Radix2Inverse](https://numerics.mathdotnet.com/api/MathNet.Numerics.IntegralTransforms/Fourier.htm#Radix2Inverse)_\r\n\r\n* *Bluestein Fast Fourier Transform (FFT):* In-place fast Fourier transform for arbitrary vector lengths: _[BluesteinForward](https://numerics.mathdotnet.com/api/MathNet.Numerics.IntegralTransforms/Fourier.htm#BluesteinForward)_, _[url:BluesteinInverse](https://numerics.mathdotnet.com/api/MathNet.Numerics.IntegralTransforms/Fourier.htm#BluesteinInverse)_\r\n\r\nFurthermore, the _[Transform](https://numerics.mathdotnet.com/api/MathNet.Numerics.IntegralTransforms/Fourier.htm)_ class provides a shortcut for the Bluestein FFT using static methods which are even easier to use: _[FourierForward](https://numerics.mathdotnet.com/api/MathNet.Numerics.IntegralTransforms/Transform.htm#FourierForward)_, _[FourierInverse](https://numerics.mathdotnet.com/api/MathNet.Numerics.IntegralTransforms/Transform.htm#FourierInverse)_.\r\n\r\nCode Sample using the Transform class:\r\n\r\n [lang=csharp]\r\n // create a complex sample vector of length 96\r\n Complex[] samples = SignalGenerator.EquidistantInterval(\r\n t =\u003E new Complex(1.0 / (t * t \u002B 1.0), t / (t * t \u002B 1.0)),\r\n -16, 16, 96);\r\n\r\n // inplace bluestein FFT with default options\r\n Transform.FourierForward(samples);\r\n\r\nFourier Options:\r\n\r\n* *Default:* Uses a negative exponent sign in forward transformations, and symmetric scaling (that is, sqrt(1/N) for both forward and inverse transformation). This is the convention used in Maple and is widely accepted in the educational sector (due to the symmetry).\r\n* *AsymmetricScaling:* Set this flag to suppress scaling on the forward transformation but scale the inverse transform with 1/N.\r\n* *NoScaling:* Set this flag to suppress scaling for both forward and inverse transformation. Note that in this case if you apply first the forward and then inverse transformation you won\u0027t get back the original signal (by factor N/2).\r\n* *InverseExponent:* Uses the positive instead of the negative sign in the forward exponent, and the negative (instead of positive) exponent in the inverse transformation.\r\n* *Matlab:* Use this flag if you need MATLAB compatibility. Equals to setting the _AsymmetricScaling_ flag. This matches the definition used in the [url:wikipedia article|https://en.wikipedia.org/wiki/Discrete_Fourier_transform].\r\n* *NumericalRecipes:* Use this flag if you need Numerical Recipes compatibility. Equal to setting both the _InverseExponent_ and the _NoScaling_ flags.\r\n\r\nUseful symmetries of the Fourier transform:\r\n\r\n* h(t) is real valued \u003C=\u003E real part of H(f) is even, imaginary part of H(f) is odd\r\n* h(t) is imaginary valued \u003C=\u003E real part of H(f) is odd, imaginary part of H(f) is even\r\n* h(t) is even \u003C=\u003E H(f) is even\r\n* h(t) is odd \u003C=\u003E H(f) is odd\r\n* h(t) is real-valued even \u003C=\u003E H(f) is real-valued even\r\n* h(t) is real-valued odd \u003C=\u003E H(f) is imaginary-valued odd\r\n* h(t) is imaginary-valued even \u003C=\u003E H(f) is imaginary-valued even\r\n* h(t) is imaginary-valued odd \u003C=\u003E H(f) is real-valued odd\r\n\r\n\r\nHartley Space: Discrete Hartley Transform\r\n-----------------------------------------\r\n\r\n...\r\n"},{"uri":"https://numerics.mathdotnet.com/Integration.html","title":"Numerical Integration\r\n","content":" [hide]\r\n #I \u0022../../out/lib/net40\u0022\r\n #r \u0022MathNet.Numerics.dll\u0022\r\n #r \u0022MathNet.Numerics.FSharp.dll\u0022\r\n open System.Numerics\r\n open MathNet.Numerics\r\n open MathNet.Numerics.Integration\r\n\r\nNumerical Integration\r\n=====================\r\n\r\nThe following double precision numerical integration or quadrature rules are supported in Math.NET Numerics under the \u0060MathNet.Numerics.Integration\u0060 namespace. Unless stated otherwise, the examples below evaluate the integral $\\int_0^{10} x^2 \\, dx = \\frac{1000}{3} \\approx 333.\\overline{3}$.\r\n\r\nSimpson\u0027s Rule\r\n--------------\r\n\r\n [lang=csharp]\r\n // Composite approximation with 4 partitions\r\n double composite = SimpsonRule.IntegrateComposite(x =\u003E x * x, 0.0, 10.0, 4);\r\n\r\n // Approximate value using IntegrateComposite with 4 partitions is: 333.33333333333337\r\n Console.WriteLine(\u0022Approximate value using IntegrateComposite with 4 partitions is: \u0022 \u002B composite);\r\n\r\n // Three point approximation\r\n double threePoint = SimpsonRule.IntegrateThreePoint(x =\u003E x * x, 0.0, 10.0);\r\n\r\n // Approximate value using IntegrateThreePoint is: 333.333333333333\r\n Console.WriteLine(\u0022Approximate value using IntegrateThreePoint is: \u0022 \u002B threePoint);\r\n\r\nNewton Cotes Trapezium Rule\r\n---------------------------\r\n\r\n [lang=csharp]\r\n // Adaptive approximation with a relative error of 1e-5\r\n double adaptive = NewtonCotesTrapeziumRule.IntegrateAdaptive(x =\u003E x * x, 0.0, 10.0, 1e-5);\r\n\r\n // Approximate value of the integral using IntegrateAdaptive with a relative error of 1e-5 is: 333.333969116211\r\n Console.WriteLine(\u0022Approximate value using IntegrateAdaptive with a relative error of 1e-5: \u0022 \u002B adaptive);\r\n\r\n // Composite approximation with 15 partitions\r\n double composite = NewtonCotesTrapeziumRule.IntegrateComposite(x =\u003E x * x, 0.0, 10.0, 15);\r\n\r\n //Approximate value of the integral using IntegrateComposite with 15 partitions is: 334.074074074074\r\n Console.WriteLine(\u0022Approximate value using IntegrateComposite with 15 partitions is: \u0022 \u002B composite);\r\n\r\n // Two point approximation\r\n double twoPoint = NewtonCotesTrapeziumRule.IntegrateTwoPoint(x =\u003E x * x, 0.0, 10.0);\r\n\r\n //Approximate value using IntegrateTwoPoint is: 500\r\n Console.WriteLine(\u0022Approximate value using IntegrateTwoPoint is: \u0022 \u002B twoPoint);\r\n\r\nDouble-Exponential Transformation\r\n---------------------------------\r\nThe Double-Exponential Transformation is suited for integration of smooth functions with no discontinuities, derivative discontinuities, and poles inside the interval.\r\n\r\n [lang=csharp]\r\n // Approximate using a relative error of 1e-5.\r\n double integrate = DoubleExponentialTransformation.Integrate(x =\u003E x * x, 0.0, 10.0, 1e-5);\r\n\r\n // Approximate value using a relative error of 1e-5 is: 333.333333333332\r\n Console.WriteLine(\u0022Approximate value using a relative error of 1e-5 is: \u0022 \u002B integrate);\r\n\r\nGauss-Legendre Rule\r\n-------------------\r\nA fixed-order Gauss-Legendre integration routine is provided for fast integration of smooth functions with known polynomial order. The N-point Gauss-Legendre rule is exact for polynomials of order $2N-1$ or less. For example, these rules are useful when integrating basis functions to form mass matrices for the Galerkin method [[GSL]](https://www.gnu.org/software/gsl/).\r\n\r\nThe basic idea of Gauss-Legendre integration is to approximate the integral of a function $f(x)$ using $N$ Weights $w_i$ and abscissas (or nodes) $x_i$.\r\n\r\n$$$\r\n\\int_a^b f(x) \\, dx \\approx \\sum_{i = 0}^{N - 1} w_i f(x_i)\r\n\r\nThis algorithm calculates the abscissas and weights for a given order and integration interval. For efficiency, pre-computed abscissas and weights for the orders $ N = 2 - 20, \\, 32, \\, 64, \\, 96, 100, \\, 128, \\, 256, \\, 512, \\, 1024$ are used. Otherwise, they are calculated on the fly using Newton\u0027s method. For more information on the algorithm see [[Holoborodko, Pavel] ](https://www.holoborodko.com/pavel/numerical-methods/numerical-integration/).\r\n\r\n### Abscissas and Weights\r\n\r\nWe\u0027ll first use the abscissas and weights to approximate an integral using a 5-point Gauss-Legendre rule\r\n\r\n [lang=csharp]\r\n // Create a 5-point Gauss-Legendre rule over the integration interval [0, 10]\r\n GaussLegendreRule rule = new GaussLegendreRule(0.0, 10.0, 5);\r\n\r\n double sum = 0; // Will hold the approximate value of the integral\r\n for (int i = 0; i \u003C rule.Order; i\u002B\u002B) // rule.Order = 5\r\n {\r\n // Access the ith abscissa and weight\r\n sum \u002B= rule.GetWeight(i) * rule.GetAbscissa(i) * rule.GetAbscissa(i);\r\n }\r\n\r\n // Approximate value is: 333.333333333333\r\n Console.WriteLine(\u0022Approximate value is: \u0022 \u002B sum);\r\n\r\nIf you prefer direct access to the abscissas and weights, as opposed to using the methods\r\n\r\n- \u0060\u0060\u0060double GetAbscissa(int i)\u0060\u0060\u0060\r\n- \u0060\u0060\u0060double GetWeight(int i)\u0060\u0060\u0060\r\n\r\nthen use the properties \u0060Abscissas\u0060 and \u0060Weights\u0060\r\n\r\n [lang=csharp]\r\n // Create a 5-point Gauss-Legendre rule over the integration interval [0, 10]\r\n GaussLegendreRule rule = new GaussLegendreRule(0.0, 10.0, 5);\r\n\r\n double[] x = rule.Abscissas; // Creates a clone and returns array of abscissas\r\n double[] w = rule.Weights; // Creates a clone and returns array of weights\r\n\r\n double sum = 0; // Will hold the approximate value of the integral\r\n for (int i = 0; i \u003C rule.Order; i\u002B\u002B) // rule.Order = 5\r\n {\r\n // Access the ith abscissa and weight\r\n sum \u002B= w[i] * x[i] * x[i];\r\n }\r\n\r\n // Approximate value is: 333.333333333333\r\n Console.WriteLine(\u0022Approximate value is: \u0022 \u002B sum);;\r\n\r\nIn addition to obtaining the abscissas and weights, the order and integration interval can be obtained\r\n\r\n [lang=csharp]\r\n // Create a 5-point Gauss-Legendre rule over the integration interval [0, 10]\r\n GaussLegendreRule rule = new GaussLegendreRule(0.0, 10.0, 5);\r\n\r\n // The order of the rule is: 5\r\n Console.WriteLine(\u0022The order of the rule is: \u0022 \u002B rule.Order);\r\n\r\n // The lower integral bound is 0\r\n Console.WriteLine(\u0022The lower integral bound is: \u0022 \u002B rule.IntervalBegin);\r\n\r\n // The upper integral bound is 10\r\n Console.WriteLine(\u0022The upper integral bound is: \u0022 \u002B rule.IntervalEnd);\r\n\r\n### Integrate Method\r\n\r\nFor convenience, we provide an overloaded static method \u0060double Integrate(...)\u0060 which preforms 1D and 2D integration of a function. The first parameter to the method is a delegate of type \u0060Func\u003Cdouble, double\u003E\u0060 or \u0060Func\u003Cdouble, double, double\u003E\u0060 for 1D and 2D integration respectively. So for example\r\n\r\n [lang=csharp]\r\n // 1D integration using a 5-point Gauss-Legendre rule over the integration interval [0, 10]\r\n double integrate1D = GaussLegendreRule.Integrate(x =\u003E x * x, 0.0, 10.0, 5);\r\n\r\n // Approximate value of the 1D integral is: 333.333333333333\r\n Console.WriteLine(\u0022Approximate value of the 1D integral is: \u0022 \u002B integrate1D);\r\n\r\n // 2D integration using a 5-point Gauss-Legendre rule over the integration interval [0, 10] X [1, 2]\r\n double integrate2D = GaussLegendreRule.Integrate((x, y) =\u003E (x * x) * (y * y), 0.0, 10.0, 1.0, 2.0, 5);\r\n\r\n // Approximate value of the 2D integral is: 777.777777777778\r\n Console.WriteLine(\u0022Approximate value of the 2D integral is: \u0022 \u002B integrate2D);\r\n\r\nwhere we used $\\int_0^{10}\\int_1^2 x^2 y^2 \\,dydx = \\frac{7000}{9} \\approx 777.\\overline{7}$ for the 2D integral example.\r\n"},{"uri":"https://numerics.mathdotnet.com/Interpolation.html","title":"Interpolation\r\n","content":" [hide]\r\n #I \u0022../../out/lib/net40\u0022\r\n #r \u0022MathNet.Numerics.dll\u0022\r\n #r \u0022MathNet.Numerics.FSharp.dll\u0022\r\n open System.Numerics\r\n open MathNet.Numerics\r\n open MathNet.Numerics.Interpolation\r\n\r\nInterpolation\r\n=============\r\n\r\nNamespace: MathNet.Numerics.Interpolation\r\n\r\nInterpolation is a two-phased operation in Math.NET Numerics:\r\n\r\n1. Create an interpolation scheme for the chosen algorithm and optimized for the given sample points. You get back a class that implements the _IInterpolation_ interface.\r\n2. Use this scheme to compute values at arbitrary points. Some interpolation algorithms also allow you to compute the derivative and the indefinite integral at that point.\r\n\r\nThe static \u0060Interpolate\u0060 class provides simple factory methods to create the interpolation scheme in a simple method call:\r\n\r\n* _RationalWithoutPoles_, creates a Floater-Hormann barycentric interpolation\r\n* _RationalWithPoles_, creates a Bulirsch \u0026 Stoer rational interpolation\r\n* _LinearBetweenPoints_, creates a linear spline interpolation\r\n\r\nIf unsure, we recommend using _RationalWithoutPoles_ for most cases.\r\n\r\nAlternatively you can also use the algorithms directly, they\u0027re publicly available in the _Algorithms_ sub-namespace for those who want to use a specific algorithm. The following algorithms are available:\r\n\r\n\r\nInterpolation on equidistant sample points\r\n------------------------------------------\r\n\r\n* *Polynomial*: Barycentric Algorithm\r\n\r\n\r\nInterpolation on arbitrary sample points\r\n----------------------------------------\r\n\r\n* *Rational pole-free*: Barycentric Floater-Hormann Algorithm\r\n* *Rational with poles*: Bulirsch \u0026 Stoer Algorithm\r\n* *Neville Polynomial*: Neville Algorithm. Note that the Neville algorithm performs very badly on equidistant points. If you need to interpolate a polynomial on equidistant points, we recommend to use the barycentric algorithm instead.\r\n* *Linear Spline*\r\n* *Cubic Spline* with boundary conditions\r\n* *Natural Cubic Spline*\r\n* *Akima Cubic Spline*\r\n* *Monotone Cubic Spline*: Monotone-preserving piecewise cubic Hermite interpolating polynomial (PCHIP), based on Fritsch \u0026 Carlson (1980).\r\n\r\n\r\nInterpolation with additional data\r\n----------------------------------\r\n\r\n* *Generic Barycentric Interpolation*, requires barycentric weights\r\n* *Generic Spline*, requires spline coefficients\r\n* *Generic Cubic Hermite Spline*, requires the derivatives\r\n"},{"uri":"https://numerics.mathdotnet.com/LinearEquations.html","title":"Linear Equation Systems\r\n","content":" [hide]\r\n #I \u0022../../out/lib/net40\u0022\r\n #r \u0022MathNet.Numerics.dll\u0022\r\n #r \u0022MathNet.Numerics.FSharp.dll\u0022\r\n open System.Numerics\r\n open MathNet.Numerics\r\n open MathNet.Numerics.LinearAlgebra\r\n\r\nLinear Equation Systems\r\n=======================\r\n\r\nA system of linear equations is a collection of linear equations involving the same set of variables:\r\n\r\n$$$\r\n\\begin{alignat}{7}\r\n3x \u0026\\; \u002B \\;\u0026 2y \u0026\\; - \\;\u0026 z \u0026\\; = \\;\u0026 1 \u0026 \\\\\r\n2x \u0026\\; - \\;\u0026 2y \u0026\\; \u002B \\;\u0026 4z \u0026\\; = \\;\u0026 -2 \u0026 \\\\\r\n-x \u0026\\; \u002B \\;\u0026 \\tfrac{1}{2} y \u0026\\; - \\;\u0026 z \u0026\\; = \\;\u0026 0 \u0026\r\n\\end{alignat}\r\n\r\nMore generally, we can write\r\n\r\n$$$\r\n\\begin{alignat}{7}\r\na_{11} x_1 \u0026\u0026\\; \u002B \\;\u0026\u0026 a_{12} x_2 \u0026\u0026\\; \u002B \\cdots \u002B \\;\u0026\u0026 a_{1n} x_n \u0026\u0026\\; = \\;\u0026\u0026\u0026 b_1 \\\\\r\na_{21} x_1 \u0026\u0026\\; \u002B \\;\u0026\u0026 a_{22} x_2 \u0026\u0026\\; \u002B \\cdots \u002B \\;\u0026\u0026 a_{2n} x_n \u0026\u0026\\; = \\;\u0026\u0026\u0026 b_2 \\\\\r\n\\vdots\\;\\;\\; \u0026\u0026 \u0026\u0026 \\vdots\\;\\;\\; \u0026\u0026 \u0026\u0026 \\vdots\\;\\;\\; \u0026\u0026 \u0026\u0026\u0026 \\;\\vdots \\\\\r\na_{m1} x_1 \u0026\u0026\\; \u002B \\;\u0026\u0026 a_{m2} x_2 \u0026\u0026\\; \u002B \\cdots \u002B \\;\u0026\u0026 a_{mn} x_n \u0026\u0026\\; = \\;\u0026\u0026\u0026 b_m \\\\\r\n\\end{alignat}\r\n\r\nwhere we all parameters $a_{ij}$ and $b_i$ are known and we would like to find $x_j$ that satisfy\r\nall these equations. If we have the same number $n$ of unknown variables $x_j$ as number of\r\nequations $m$, and all these equations are independent, then there is a unique solution.\r\n\r\nThis is a fundamental problem in the domain of linear algebra, and we can use its power to find the solution.\r\nAccordingly we can write the equivalent problem with matrices and vectors:\r\n\r\n$$$\r\n\\mathbf{A}=\r\n\\begin{bmatrix}\r\na_{11} \u0026 a_{12} \u0026 \\cdots \u0026 a_{1n} \\\\\r\na_{21} \u0026 a_{22} \u0026 \\cdots \u0026 a_{2n} \\\\\r\n\\vdots \u0026 \\vdots \u0026 \\ddots \u0026 \\vdots \\\\\r\na_{m1} \u0026 a_{m2} \u0026 \\cdots \u0026 a_{mn}\r\n\\end{bmatrix},\\quad\r\n\\mathbf{x}=\\begin{bmatrix}x_1\\\\x_2\\\\ \\vdots \\\\x_n\\end{bmatrix},\\quad\r\n\\mathbf{b}=\\begin{bmatrix}b_1\\\\b_2\\\\ \\vdots \\\\b_m\\end{bmatrix}\r\n\r\nsuch that\r\n\r\n$$$\r\n\\mathbf{A}\\mathbf{x}=\\mathbf{b}\r\n\r\nThe initial example system would then look like this:\r\n\r\n$$$\r\n\\begin{bmatrix}3 \u0026 2 \u0026 -1 \\\\2 \u0026 -2 \u0026 4 \\\\-1 \u0026 \\tfrac{1}{2} \u0026 -1\\end{bmatrix}\r\n\\begin{bmatrix}x\\\\y\\\\z\\end{bmatrix}\r\n\\;=\\;\r\n\\begin{bmatrix}1\\\\-2\\\\0\\end{bmatrix}\r\n\r\nWhich we can solve explicitly with the LU-decomposition, or simply by using the Solve method:\r\n\r\n [lang=csharp]\r\n var A = Matrix\u003Cdouble\u003E.Build.DenseOfArray(new double[,] {\r\n { 3, 2, -1 },\r\n { 2, -2, 4 },\r\n { -1, 0.5, -1 }\r\n });\r\n var b = Vector\u003Cdouble\u003E.Build.Dense(new double[] { 1, -2, 0 });\r\n var x = A.Solve(b);\r\n\r\nThe resulting $\\mathbf{x}$ is $[1,\\;-2,\\;-2]$, hence the solution $x=1,\\;y=-2,\\;z=-2$.\r\n\r\nIn F# the syntax is a bit lighter:\r\n\r\n [lang=fsharp]\r\n let A = matrix [[ 3.0; 2.0; -1.0 ]\r\n [ 2.0; -2.0; 4.0 ]\r\n [ -1.0; 0.5; -1.0 ]]\r\n let b = vector [ 1.0; -2.0; 0.0 ]\r\n let x = A.Solve(b) // 1;-2;-2\r\n\r\n\r\nNormalizing Equation Systems\r\n----------------------------\r\n\r\nIn practice, a linear equation system to be solved is often not in the standard form required\r\nto use the linear algebra approach. For example, let\u0027s have a look at the following system:\r\n\r\n$$$\r\n\\begin{bmatrix}1 \u0026 2 \u0026 3 \u0026 4\\\\2 \u0026 3 \u0026 4 \u0026 5\\\\3 \u0026 4 \u0026 5 \u0026 6\\\\4 \u0026 5 \u0026 6 \u0026 7\\end{bmatrix}\r\n\\begin{bmatrix}0\\\\0\\\\V\\\\T\\end{bmatrix}\r\n\\;=\\;\r\n\\begin{bmatrix}F\\\\M\\\\20\\\\0\\end{bmatrix}\r\n\r\nThe first two values of the solution vector $[0,\\;0,\\;V,\\;T]$ are constant zero, so we can simplify\r\nthe system to:\r\n\r\n$$$\r\n\\begin{bmatrix}3 \u0026 4\\\\4 \u0026 5\\\\5 \u0026 6\\\\6 \u0026 7\\end{bmatrix}\r\n\\begin{bmatrix}V\\\\T\\end{bmatrix}\r\n\\;=\\;\r\n\\begin{bmatrix}F\\\\M\\\\20\\\\0\\end{bmatrix}\r\n\r\nThen we need to subtract the two unknowns from the right side back from the left (so that they\r\nbecome zero on the right side), by introducing a new column each. First we subtract\r\n$[F,\\;0,\\;0,\\;0]^T$ from both sides:\r\n\r\n$$$\r\n\\begin{bmatrix}3 \u0026 4 \u0026 -1\\\\4 \u0026 5 \u0026 0\\\\5 \u0026 6 \u0026 0\\\\6 \u0026 7 \u0026 0\\end{bmatrix}\r\n\\begin{bmatrix}V\\\\T\\\\F\\end{bmatrix}\r\n\\;=\\;\r\n\\begin{bmatrix}0\\\\M\\\\20\\\\0\\end{bmatrix}\r\n\r\nThen we subtract $[0,\\;M,\\;0,\\;0]^T$ from both sides the same way:\r\n\r\n$$$\r\n\\begin{bmatrix}3 \u0026 4 \u0026 -1 \u0026 0\\\\4 \u0026 5 \u0026 0 \u0026 -1\\\\5 \u0026 6 \u0026 0 \u0026 0\\\\6 \u0026 7 \u0026 0 \u0026 0\\end{bmatrix}\r\n\\begin{bmatrix}V\\\\T\\\\F\\\\M\\end{bmatrix}\r\n\\;=\\;\r\n\\begin{bmatrix}0\\\\0\\\\20\\\\0\\end{bmatrix}\r\n\r\nWhich is in standard from, so we can solve normally:\r\n\r\n [lang=fsharp]\r\n let A\u0027 = matrix [[ 3.0; 4.0; -1.0; 0.0 ]\r\n [ 4.0; 5.0; 0.0; -1.0 ]\r\n [ 5.0; 6.0; 0.0; 0.0; ]\r\n [ 6.0; 7.0; 0.0; 0.0 ]]\r\n let b\u0027 = vector [ 0.0; 0.0; 20.0; 0.0 ]\r\n let x\u0027 = A\u0027.Solve(b\u0027) // -140; 120; 60; 40\r\n"},{"uri":"https://numerics.mathdotnet.com/MatlabFiles.html","title":"MATLAB Level-5 Mat Files\r\n","content":"MATLAB Level-5 Mat Files\r\n========================\r\n\r\nLevel-5 MATLAB Mat files are popular as binary file container for storing one or more matrices.\r\nMath.NET Numerics provides basic support for such Mat files with the **MathNet.Numerics.Data.Matlab** package,\r\nwhich is available on NuGet as separate package and not included in the basic distribution.\r\n\r\n\r\nReading matrices from a MATLAB file\r\n-----------------------------------\r\n\r\nThe \u0060MatlabReader\u0060 class provides static functions to list all matrices stored in a MAT file or stream,\r\nand to read them individually as Math.NET matrices:\r\n\r\n [lang=csharp]\r\n using MathNet.Numerics.LinearAlgebra;\r\n using MathNet.Numerics.Data.Matlab;\r\n\r\n // read the first matrix as double\r\n Matrix\u003Cdouble\u003E m = MatlabReader.Read\u003Cdouble\u003E(\u0022collection.mat\u0022);\r\n\r\n // read a specific matrix named \u0022vd\u0022:\r\n Matrix\u003Cdouble\u003E m = MatlabReader.Read\u003Cdouble\u003E(\u0022collection.mat\u0022, \u0022vd\u0022);\r\n\r\n // we can also choose to convert to a different type:\r\n Matrix\u003CComplex\u003E m = MatlabReader.Read\u003CComplex\u003E(\u0022collection.mat\u0022);\r\n\r\n // read all matrices of a file by name into a dictionary\r\n Dictionary\u003Cstring,Matrix\u003Cdouble\u003E\u003E ms =\r\n MatlabReader.ReadAll\u003Cdouble\u003E(\u0022collection.mat\u0022);\r\n\r\n // read the matrices named \u0022Ad\u0022 and \u0022vd\u0022 into a dictionary\r\n var ms = MatlabReader.ReadAll\u003Cdouble\u003E(\u0022collection.mat\u0022, \u0022vd\u0022, \u0022Ad\u0022);\r\n\r\nAlternatively the reader can list all matrices of a file into named data elements,\r\nwhich can then be read into matrices individually. This is useful e.g. if we need to\r\nread some of the matrices to a different type:\r\n\r\n [lang=csharp]\r\n List\u003CMatlabMatrix\u003E ms = MatlabReader.List(\u0022collection.mat\u0022);\r\n Matrix\u003Cdouble\u003E Ad = MatlabReader.Unpack\u003Cdouble\u003E(ms.Find(m =\u003E m.Name == \u0022Ad\u0022));\r\n Matrix\u003Cfloat\u003E vd = MatlabReader.Unpack\u003Cfloat\u003E(ms.Find(m =\u003E m.Name == \u0022vd\u0022));\r\n\r\n\r\nWriting matrices to a MATLAB file\r\n---------------------------------\r\n\r\nThe dual to the reader above is the \u0060MatlabWriter\u0060 class that can serialize matrices\r\nto a MATLAB file or stream. Like the reader, the writer can use \u0060MatlabMatrix\u0060 data elements\r\nto compose packed matrices into a file. Each matrix has a name which must not contain spaces.\r\n\r\n [lang=csharp]\r\n var matrices = new List\u003CMatlabMatrix\u003E();\r\n m.Add(MatlabWriter.Pack(myFirstMatrix, \u0022m1\u0022);\r\n m.Add(MatlabWriter.Pack(mySecondMatrix, \u0022m2\u0022);\r\n MatlabWrier.Store(\u0022file.mat\u0022, matrices);\r\n\r\nBut there are also direct routines if only a single matrix or matrices of all the same data type\r\nare to be stored in a file:\r\n\r\n [lang=csharp]\r\n // write a single matrix \u0022myMatrix\u0022 and name it \u0022m1\u0022.\r\n MatlabWriter.Write(\u0022file.mat\u0022, myMatrix, \u0022m1\u0022);\r\n\r\n // write multiple matrices, from a list of matrices and a list of their names:\r\n MatlabWriter.Write(\u0022file.mat\u0022, new[] { m1, m2 }, new[] { \u0022m1\u0022, \u0022m2\u0022 });\r\n\r\n // write a dictionary of matrices:\r\n var dict = new Dictionary\u003Cstring, Matrix\u003Cdouble\u003E\u003E();\r\n dict.Add(\u0022m1\u0022, m1);\r\n dict.Add(\u0022m2\u0022, m2);\r\n MatlabWriter.Write(\u0022file.mat\u0022, dict);\r\n\r\n\r\nAlternatives\r\n------------\r\n\r\nThe data extension packages also offer other ways to serialize a matrix to a text file.\r\nAmong others:\r\n\r\n* [Delimited Text Files (CSV \u0026 TSV)](CSV.html)\r\n* [NIST MatrixMarket text files](MatrixMarket.html)\r\n"},{"uri":"https://numerics.mathdotnet.com/Matrix.html","title":"Matrices and Vectors\r\n","content":" [hide]\r\n #I \u0022../../out/lib/net40\u0022\r\n #r \u0022MathNet.Numerics.dll\u0022\r\n #r \u0022MathNet.Numerics.FSharp.dll\u0022\r\n open System.Numerics\r\n open MathNet.Numerics\r\n open MathNet.Numerics.LinearAlgebra\r\n open MathNet.Numerics.Distributions\r\n\r\nMatrices and Vectors\r\n====================\r\n\r\nMath.NET Numerics includes rich types for matrices and vectors.\r\nThey support both single and double precision, real and complex floating point numbers.\r\n\r\n$$$\r\n\\mathbf{A}=\r\n\\begin{bmatrix}\r\na_{0,0} \u0026 a_{0,1} \u0026 \\cdots \u0026 a_{0,(n-1)} \\\\\r\na_{1,0} \u0026 a_{1,1} \u0026 \\cdots \u0026 a_{1,(n-1)} \\\\\r\n\\vdots \u0026 \\vdots \u0026 \\ddots \u0026 \\vdots \\\\\r\na_{(m-1),0} \u0026 a_{(m-1),1} \u0026 \\cdots \u0026 a_{(m-1),(n-1)}\r\n\\end{bmatrix},\\quad\r\n\\mathbf{v}=\\begin{bmatrix}v_0\\\\v_1\\\\ \\vdots \\\\v_{n-1}\\end{bmatrix}\r\n\r\nLike all data structures in .Net they are 0-indexed, i.e. the top left cell has index (0,0). In matrices,\r\nthe first index always refers to the row and the second index to the column.\r\nEmpty matrices or vectors are not supported, i.e. each dimension must have a length of at least 1.\r\n\r\n### Context: Linear Algebra\r\n\r\nThe context and primary scenario for these types is linear algebra. Their API is broad enough\r\nto use them in other contexts as well, but they are *not* optimized for geometry or\r\nas general purpose storage structure as common in MATLAB. This is intentional, as\r\nspatial problems, geography and geometry have quite different usage patterns and requirements\r\nto linear algebra. All places where Math.NET Numerics can be used have a strong\r\nprogramming language with their own data structures. For example, if you have a collection of vectors,\r\nconsider to store them in a list or array of vectors, not in a matrix (unless you need matrix operations, of course).\r\n\r\nStorage Layout\r\n--------------\r\n\r\nBoth dense and sparse vectors are supported:\r\n\r\n* **Dense Vector** uses a single array of the same length as the vector.\r\n* **Sparse Vector** uses two arrays which are usually much shorter than the vector.\r\n One array stores all values that are not zero, the other stores their indices.\r\n They are sorted ascendingly by index.\r\n\r\nMatrices can be either dense, diagonal or sparse:\r\n\r\n* **Dense Matrix** uses a single array in column-major order.\r\n* **Diagonal Matrix** stores only the diagonal values, in a single array.\r\n* **Sparse Matrix** stores non-zero values in 3 arrays in the standard compressed sparse row (CSR) format.\r\n One array stores all values that are not zero, another array of the same length stores\r\n the their corresponding column index. The third array of the length of the number of rows plus one,\r\n stores the offsets where each row starts, and the total number of non-zero values in the last field.\r\n\r\nIf your data contains only very few zeros, using the sparse variant is orders of magnitudes\r\nslower than their dense counterparts, so consider to use dense types unless the data is very sparse (i.e. almost all zeros).\r\n\r\nCreating Matrices and Vectors\r\n-----------------------------\r\n\r\nThe \u0060Matrix\u003CT\u003E\u0060 and \u0060Vector\u003CT\u003E\u0060 types are defined in the \u0060MathNet.Numerics.LinearAlgebra\u0060 namespace.\r\n\r\nFor technical and performance reasons there are distinct implementations for each data type.\r\nFor example, for double precision numbers there is a \u0060DenseMatrix\u0060 class in the \u0060MathNet.Numerics.LinearAlgebra.Double\u0060\r\nnamespace. You do not normally need to be aware of that, but as consequence the generic \u0060Matrix\u003CT\u003E\u0060 type is abstract\r\nand we need other ways to create a matrix or vector instance.\r\n\r\nThe matrix and vector builder provide functions to create instances from a variety of formats or approaches.\r\n\r\n [lang=csharp]\r\n // create a dense matrix with 3 rows and 4 columns\r\n // filled with random numbers sampled from the standard distribution\r\n Matrix\u003Cdouble\u003E m = Matrix\u003Cdouble\u003E.Build.Random(3, 4);\r\n\r\n // create a dense zero-vector of length 10\r\n Vector\u003Cdouble\u003E v = Vector\u003Cdouble\u003E.Build.Dense(10);\r\n\r\nSince within an application you often only work with one specific data type, a common trick to keep this a bit shorter\r\nis to define shortcuts to the builders:\r\n\r\n [lang=csharp]\r\n var M = Matrix\u003Cdouble\u003E.Build;\r\n var V = Vector\u003Cdouble\u003E.Build;\r\n\r\n // build the same as above\r\n var m = M.Random(3, 4);\r\n var v = V.Dense(10);\r\n\r\nThe builder functions usually start with the layout (Dense, Sparse, Diagonal),\r\nso if we\u0027d like to build a sparse matrix, intellisense will list all available options\r\ntogether once you type \u0060M.Sparse\u0060.\r\n\r\nThere are variants to generate synthetic matrices, for example:\r\n\r\n [lang=csharp]\r\n // 3x4 dense matrix filled with zeros\r\n M.Dense(3, 4);\r\n\r\n // 3x4 dense matrix filled with 1.0.\r\n M.Dense(3, 4, 1.0);\r\n\r\n // 3x4 dense matrix where each field is initialized using a function\r\n M.Dense(3, 4, (i,j) =\u003E 100*i \u002B j);\r\n\r\n // 3x4 square dense matrix with each diagonal value set to 2.0\r\n M.DenseDiagonal(3, 4, 2.0);\r\n\r\n // 3x3 dense identity matrix\r\n M.DenseIdentity(3);\r\n\r\n // 3x4 dense random matrix sampled from a Gamma distribution\r\n M.Random(3, 4, new Gamma(1.0, 5.0));\r\n\r\n\r\nBut often we already have data available in some format and\r\nneed a matrix representing the same data. Whenever a function contains\r\n\u0022Of\u0022 in its name it does create a copy of the original data.\r\n\r\n [lang=csharp]\r\n // Copy of an existing matrix (can also be sparse or diagonal)\r\n Matrix\u003Cdouble\u003E x = ...\r\n M.DenseOfMatrix(x);\r\n\r\n // Directly bind to an existing column-major array without copying (note: no \u0022Of\u0022)\r\n double[] x = existing...\r\n M.Dense(3, 4, x);\r\n\r\n // From a 2D-array\r\n double[,] x = {{ 1.0, 2.0 },\r\n { 3.0, 4.0 }};\r\n M.DenseOfArray(x);\r\n\r\n // From an enumerable of values and their coordinates\r\n Tuple\u003Cint,int,double\u003E[] x = {Tuple.Create(0,0,2.0), Tuple.Create(0,1,-3.0)};\r\n M.DenseOfIndexed(3,4,x);\r\n\r\n // From an enumerable in column major order (column by column)\r\n double[] x = {1.0, 2.0, 3.0, 4.0};\r\n M.DenseOfColumnMajor(2, 2, x);\r\n\r\n // From an enumerable of enumerable-columns (optional with explicit size)\r\n IEnumerable\u003CIEnumerable\u003Cdouble\u003E\u003E x = ...\r\n M.DenseOfColumns(x);\r\n\r\n // From a params-array of array-columns (or an enumerable of them)\r\n M.DenseOfColumnArrays(new[] {2.0, 3.0}, new[] {4.0, 5.0});\r\n\r\n // From a params-array of column vectors (or an enumerable of them)\r\n M.DenseOfColumnVectors(V.Random(3), V.Random(3));\r\n\r\n // Equivalent variants also for rows or diagonals:\r\n M.DenseOfRowArrays(new[] {2.0, 3.0}, new[] {4.0, 5.0});\r\n M.DenseOfDiagonalArray(new[] {2.0, 3.0, 4.0});\r\n\r\n // if you already have existing matrices and want to concatenate them\r\n Matrix\u003Cdouble\u003E[,] x = ...\r\n M.DenseOfMatrixArray(x);\r\n\r\nVery similar variants also exist for sparse and diagonal matrices, prefixed\r\nwith \u0060Sparse\u0060 and \u0060Diagonal\u0060 respectively.\r\n\r\nThe approach for vectors is exactly the same:\r\n\r\n [lang=csharp]\r\n // Standard-distributed random vector of length 10\r\n V.Random(10);\r\n\r\n // All-zero vector of length 10\r\n V.Dense(10);\r\n\r\n // Each field is initialized using a function\r\n V.Dense(10, i =\u003E i*i);\r\n\r\n // From an enumerable of values and their index\r\n Tuple\u003Cint,double\u003E[] x = {Tuple.Create(3,2.0), Tuple.Create(1,-3.0)};\r\n V.DenseOfIndexed(x);\r\n\r\n // Directly bind to an existing array without copying (note: no \u0022Of\u0022)\r\n double[] x = existing...\r\n V.Dense(x);\r\n\r\n### Creating matrices and vectors in F#\r\n\r\nIn F# we can use the builders just like in C#, but we can also use the F# modules:\r\n\r\n [lang=fsharp]\r\n let m1 = matrix [[ 2.0; 3.0 ]\r\n [ 4.0; 5.0 ]]\r\n\r\n let v1 = vector [ 1.0; 2.0; 3.0 ]\r\n\r\n // dense 3x4 matrix filled with zeros.\r\n // (usually the type is inferred, but not for zero matrices)\r\n let m2 = DenseMatrix.zero\u003Cfloat\u003E 3 4\r\n\r\n // dense 3x4 matrix initialized by a function\r\n let m3 = DenseMatrix.init 3 4 (fun i j -\u003E float (i\u002Bj))\r\n\r\n // diagonal 4x4 identity matrix of single precision\r\n let m4 = DiagonalMatrix.identity\u003Cfloat32\u003E 4\r\n\r\n // dense 3x4 matrix created from a sequence of sequence-columns\r\n let x = Seq.init 4 (fun c -\u003E Seq.init 3 (fun r -\u003E float (100*r \u002B c)))\r\n let m5 = DenseMatrix.ofColumnSeq x\r\n\r\n // random matrix with standard distribution:\r\n let m6 = DenseMatrix.randomStandard\u003Cfloat\u003E 3 4\r\n\r\n // random matrix with a uniform and one with a Gamma distribution:\r\n let m7a = DenseMatrix.random\u003Cfloat\u003E 3 4 (ContinuousUniform(-2.0, 4.0))\r\n let m7b = DenseMatrix.random\u003Cfloat\u003E 3 4 (Gamma(1.0, 2.0))\r\n\r\nOr using any other of all the available functions.\r\n\r\n\r\nArithmetics\r\n-----------\r\n\r\nAll the common arithmetic operators like \u0060\u002B\u0060, \u0060-\u0060, \u0060*\u0060, \u0060/\u0060 and \u0060%\u0060 are provided,\r\nbetween matrices, vectors and scalars. In F# there are additional pointwise\r\noperators \u0060.*\u0060, \u0060./\u0060 and \u0060.%\u0060 available for convenience.\r\n\r\n [lang=fsharp]\r\n let m = matrix [[ 1.0; 4.0; 7.0 ]\r\n [ 2.0; 5.0; 8.0 ]\r\n [ 3.0; 6.0; 9.0 ]]\r\n\r\n let v = vector [ 10.0; 20.0; 30.0 ]\r\n\r\n let v\u0027 = m * v\r\n let m\u0027 = m \u002B 2.0*m\r\n\r\n### Arithmetic Instance Methods\r\n\r\nAll other operations are covered by methods, like \u0060Transpose\u0060 and \u0060Conjugate\u0060,\r\nor in F# as functions in the Matrix module, e.g. \u0060Matrix.transpose\u0060.\r\nBut even the operators have equivalent methods. The equivalent code from\r\nabove when using instance methods:\r\n\r\n [lang=csharp]\r\n var v2 = m.Multiply(v);\r\n var m2 = m.Add(m.Multiply(2));\r\n\r\nThese methods also have an overload that accepts the result data structure as last argument,\r\nallowing to avoid allocating new structures for every single operation. Provided the\r\ndimensions match, most also allow one of the arguments to be passed as result,\r\nresulting in an in-place application. For example, an in-place version of the code above:\r\n\r\n [lang=csharp]\r\n m.Multiply(v, v); // v \u003C- m*v\r\n m.Multiply(3, m); // m \u003C- 3*m\r\n\r\n### Shortcut Methods\r\n\r\nA typical linear algebra problem is the regression normal equation\r\n$\\mathbf{X}^T\\mathbf y = \\mathbf{X}^T\\mathbf X \\mathbf p$ which we would like to solve\r\nfor $p$. By matrix inversion we get $\\mathbf p = (\\mathbf{X}^T\\mathbf X)^{-1}(\\mathbf{X}^T\\mathbf y)$.\r\nThis can directly be translated to the following code:\r\n\r\n [lang=csharp]\r\n (X.Transpose() * X).Inverse() * (X.Transpose() * y)\r\n\r\nSince products where one of the arguments is transposed are common, there are a few shortcut routines\r\nthat are more efficient:\r\n\r\n [lang=csharp]\r\n X.TransposeThisAndMultiply(X).Inverse() * X.TransposeThisAndMultiply(y)\r\n\r\nOf course in practice you would not use the matrix inverse but a decomposition:\r\n\r\n [lang=csharp]\r\n X.TransposeThisAndMultiply(X).Cholesky().Solve(X.TransposeThisAndMultiply(y))\r\n \r\n // or if the problem is small enough, simply:\r\n X.Solve(y);\r\n\r\n\r\nNorms\r\n-----\r\n\r\nWith norms we assign a \u0022size\u0022 to vectors and matrices, satisfying certain\r\nproperties pertaining to scalability and additivity. Except for the zero element,\r\nthe norm is strictly positive.\r\n\r\nVectors support the following norms:\r\n\r\n* **L1Norm** or Manhattan norm (p=1): the sum of the absolute values.\r\n* **L2Norm** or Euclidean norm (p=2): the square root of the sum of the squared values.\r\n This is the most common norm and assumed if nothing else is stated.\r\n* **InfinityNorm** (p=infinity): the maximum absolute value.\r\n* **Norm(p)**: generalized norm, essentially the p-th root of the sum of the absolute p-power of the values.\r\n\r\nSimilarly, matrices support the following norms:\r\n\r\n* **L1Norm** (induced): the maximum absolute column sum.\r\n* **L2Norm** (induced): the largest singular value of the matrix (expensive).\r\n* **InfinityNorm** (induced): the maximum absolute row sum.\r\n* **FrobeniusNorm** (entry-wise): the square root of the sum of the squared values.\r\n* **RowNorms(p)**: the generalized p-norm for each row vector.\r\n* **ColumnNorms(p)**: the generalized p-norm for each column vector.\r\n\r\nVectors can be normalized to unit p-norm with the \u0060Normalize\u0060 method, matrices can\r\nnormalize all rows or all columns to unit p-norm with \u0060NormalizeRows\u0060 and \u0060NormalizeColumns\u0060.\r\n\r\n\r\nSums\r\n----\r\n\r\nClosely related to the norms are sum functions. Vectors have a \u0060Sum\u0060 function\r\nthat returns the sum of all vector elements, and \u0060SumMagnitudes\u0060 that returns\r\nthe sum of the absolute vector elements (and is identical to the L1-norm).\r\n\r\nMatrices provide \u0060RowSums\u0060 and \u0060ColumnSums\u0060 functions that return the sum of each\r\nrow or column vector, and \u0060RowAbsoluteSums\u0060 and \u0060ColumnAbsoluteSums\u0060 for the\r\nsums of the absolute elements.\r\n\r\n\r\nCondition Number\r\n----------------\r\n\r\nThe condition number of a function measures how much the output value can change\r\nfor a small change in the input arguments. A problem with a low condition number\r\nis said to be *well-conditioned*, with a high condition number *ill-conditioned*.\r\nFor a linear equation $Ax=b$ the condition number is the maximum ratio of the\r\nrelative error in $x$ divided by the relative error in $b$. It therefore gives a bound on how\r\ninaccurate the solution $x$ will be after approximation.\r\n\r\n [lang=csharp]\r\n M.Random(4,4).ConditionNumber(); // e.g. 14.829\r\n\r\n\r\nTrace and Determinant\r\n---------------------\r\n\r\nFor a square matrix, the trace of a matrix is the sum of the elements on the main diagonal,\r\nwhich is equal to the sum of all its eigenvalues with multiplicities. Similarly, the determinant\r\nof a square matrix is the product of all its eigenvalues with multiplicities.\r\nA matrix is said to be *singular* if its determinant is zero and *non-singular* otherwise.\r\nIn the latter case the matrix is invertible and the linear equation system it\r\nrepresents has a single unique solution.\r\n\r\n [lang=csharp]\r\n var m = M.DenseOfArray(new[,] {{ 1.0, 2.0, 1.0},\r\n {-2.0, -3.0, 1.0},\r\n { 3.0, 5.0, 0.0}});\r\n\r\n m.Trace(); // -2\r\n m.Determinant(); // ~0 hence not invertible, either none or multiple solutions\r\n\r\n\r\nColumn Space, Rank and Range\r\n-----------------------------\r\n\r\nThe rank of a matrix is the dimension of its column and row space, i.e. the maximum\r\nnumber of linearly independent column and row vectors of the matrix. It is a measure\r\nof the non-degenerateness of the linear equation system the matrix represents.\r\n\r\nAn orthonormal basis of the column space can be computed with the range method.\r\n\r\n [lang=csharp]\r\n // with the same m as above\r\n m.Rank(); // 2\r\n m.Range(); // [-0.30519,0.503259,-0.808449], [-0.757315,-0.64296,-0.114355]\r\n\r\n\r\nNull Space, Nullity and Kernel\r\n------------------------------\r\n\r\nThe null space or kernel of a matrix $A$ is the set of solutions to the equation $Ax=0$.\r\nIt is the orthogonal complement to the row space of the matrix.\r\n\r\nThe nullity of a matrix is the dimension of its null space.\r\nAn orthonormal basis of the null space can be computed with the kernel method.\r\n\r\n [lang=csharp]\r\n // with the same m as above\r\n m.Nullity(); // 1\r\n m.Kernel(); // [0.845154,-0.507093,0.169031]\r\n\r\n // verify:\r\n (m * (10*m.Kernel()[0])); // ~[0,0,0]\r\n\r\n\r\nMatrix Decompositions\r\n---------------------\r\n\r\nMost common matrix decompositions are directly available as instance methods.\r\nComputing a decomposition can be expensive for large matrices, so if you need\r\nto access multiple properties of a decomposition, consider to reuse the returned instance.\r\n\r\nAll decompositions provide Solve methods than can be used to solve linear\r\nequations of the form $Ax=b$ or $AX=B$. For simplicity the Matrix class\r\nalso provides direct \u0060Solve\u0060 methods that automatically choose\r\na decomposition. See [Linear Equation Systems](LinearEquations.html) for details.\r\n\r\nCurrently these decompositions are optimized for dense matrices only,\r\nand can leverage native providers like Intel MKL if available.\r\nFor sparse data consider to use the iterative solvers instead if appropriate,\r\nor convert to dense if small enough.\r\n\r\n* **Cholesky**: Cholesky decomposition of symmetric positive definite matrices\r\n* **LU**: LU decomposition of square matrices\r\n* **QR(method)**: QR by Householder transformation.\r\n Thin by default (Q: mxn, R: nxn) but can optionally be computed fully (Q: mxm, R: mxn).\r\n* **GramSchmidt**: QR by Modified Gram-Schmidt Orthogonalization\r\n* **Svd(computeVectors)**: Singular Value Decomposition.\r\n Computation of the singular U and VT vectors can optionally be disabled.\r\n* **Evd(symmetricity)**: Eigenvalue Decomposition.\r\n If the symmetricity of the matrix is known, the algorithm can optionally skip its own check.\r\n\r\n\r\nManipulating Matrices and Vectors\r\n---------------------------------\r\n\r\nIndividual values can be get and set in matrices and vectors using the indexers\r\nor the \u0060At\u0060 methods. Using \u0060At\u0060 instead of the indexers is slightly faster but\r\nskips some range checks, so use it only after checking the range yourself.\r\n\r\n [lang=csharp]\r\n var m = Matrix\u003Cdouble\u003E.Build.Dense(3,4,(i,j) =\u003E 10*i \u002B j);\r\n m[0,0]; // 0 (row 0, column 0)\r\n m[2,0]; // 20 (row 2, column 0)\r\n m[0,2]; // 2 (row 0, column 2)\r\n m[0,2] = -1.0;\r\n m[0,2]; // -1\r\n\r\nIn F#:\r\n\r\n [lang=fsharp]\r\n m.[2,0] // 20\r\n\r\nWe can also get entire column or row vectors, or a new matrix from parts of an existing one.\r\n\r\n [lang=csharp]\r\n var m = M.Dense(6,4,(i,j) =\u003E 10*i \u002B j);\r\n m.Column(2); // [2,12,22,32,42,52]\r\n m.Row(3); // [30,31,32,33]\r\n m.SubMatrix(1,2,1,2); // [11,12; 21,22]\r\n\r\nFor each of these methods there is also a variant prefixed with \u0060Set\u0060 that can be used\r\nto overwrite those elements with the provided data.\r\n\r\n [lang=csharp]\r\n m.SetRow(3, V.Random(4));\r\n\r\nIn F# we can also use its slicing syntax:\r\n\r\n [lang=fsharp]\r\n let m = DenseMatrix.init 6 4 (fun i j -\u003E float (10*i \u002B j))\r\n m.[0,0..3] // vector [0,1,2,3]\r\n m.[1..2,0..3] // matrix [10,11,12,13; 20,21,22,23]\r\n // overwrite a sub-matrix with the content of another matrix:\r\n m.[0..1,1..2] \u003C- matrix [[ 3.0; 4.0 ]; [ 5.0; 6.0 ]]\r\n\r\nTo set the whole matrix or some of its columns or rows to zero, use one of the clear methods:\r\n\r\n [lang=csharp]\r\n m.Clear(); // set all elements to 0\r\n m.ClearColumn(2); // set the 3rd column to 0 (0-based indexing)\r\n m.ClearColumns(1,3); // set the 2nd and 4th columns to 0 (params-array)\r\n m.ClearSubMatrix(1,2,1,2); // set the 2x2 submatrix with offset 1,1 to zero\r\n\r\nBecause of the limitations of floating point numbers, we may want to set very small numbers to zero:\r\n\r\n [lang=csharp]\r\n m.CoerceZero(1e-14); // set all elements smaller than 1e-14 to 0\r\n m.CoerceZero(x =\u003E x \u003C 10); // set all elements that match a predicate function to 0.\r\n\r\nEven though matrices and vectors are mutable, their dimension is fixed and cannot be changed\r\nafter creation. However, we can still insert or remove rows or columns, or concatenate matrices together.\r\nBut all these operations will create and return a new instance.\r\n\r\n [lang=csharp]\r\n var m2 = m.RemoveRow(2); // remove the 3rd rows\r\n var m3 = m2.RemoveColumn(3); // remove the 4th column\r\n\r\n var m4 = m.Stack(m2); // new matrix with m on top and m2 on the bottom\r\n var m5 = m2.Append(m3); // new matrix with m2 on the left and m3 on the right\r\n var m6 = m.DiagonalStack(m3); // m on the top left and m3 on the bottom right\r\n\r\n\r\nEnumerators and Higher Order Functions\r\n--------------------------------------\r\n\r\nSince looping over all entries of a matrix or vector with direct access is inefficient,\r\nespecially with a sparse storage layout, and working with the raw structures is non-trivial,\r\nboth vectors and matrices provide specialized enumerators and higher order functions that\r\nunderstand the actual layout and can use it more efficiently.\r\n\r\nMost of these functions can optionally skip zero-value entries. If you do not need to handle\r\nzero-value elements, skipping them can massively speed up execution on sparse layouts.\r\n\r\n### Iterate\r\n\r\nBoth vectors and matrices have Enumerate methods that return an \u0060IEnumerable\u003CT\u003E\u0060,\r\nthat can be used to iterate through all elements. All these methods optionally\r\naccept a \u0060Zeros\u0060 enumeration to control whether zero-values may be skipped or not.\r\n\r\n* **Enumerate**: returns a straight forward enumerator over all values.\r\n* **EnumerateIndexed**: returns an enumerable with index-value-tuples.\r\n\r\nMatrices can also enumerate over all column or row vectors, or all of them\r\nwithin a range:\r\n\r\n* **EnumerateColumns**: returns an enumerable with all or a range of the column vectors.\r\n* **EnumerateColumnsIndexed**: like EnumerateColumns buth returns index-column tuples.\r\n* **EnumerateRows**: returns an enumerable with all or a range of the row vectors.\r\n* **EnumerateRowsIndexed**: like EnumerateRows buth returns index-row tuples.\r\n\r\n### Map\r\n\r\nSimilarly there are also Map methods that replace each element with the result\r\nof applying a function to its value. Or, if indexed, to its index and value.\r\n\r\n* **MapInplace(f,zeros)**: map in-place with a function on the element\u0027s value\r\n* **MapIndexedInplace(f,zeros)**: map in-place with a function on the element\u0027s index and value.\r\n* **Map(f,result,zeros)**: map into a result structure provided as argument.\r\n* **MapIndexed(f,result,zeros)**: indexed variant of Map.\r\n* **MapConvert(f,result,zeros)**: variant where the function can return a different type\r\n* **MapIndexedConvert(f,result,zeros)**: indexed variant of MapConvert.\r\n* **Map(f,zeros)**: like MapConvert but returns a new structure instead of the result argument.\r\n* **MapIndexed(f,zeros)**: indexed variant of Map.\r\n\r\nExample: Convert a complex vector to a real vector containing only the real parts in C#:\r\n\r\n [lang=csharp]\r\n Vector\u003CComplex\u003E u = Vector\u003CComplex\u003E.Build.Random(10);\r\n Vector\u003CDouble\u003E v = u.Map(c =\u003E c.Real);\r\n\r\nOr in F#:\r\n\r\n [lang=fsharp]\r\n let u = DenseVector.randomStandard\u003CComplex\u003E 10\r\n let v = u |\u003E Vector.map (fun c -\u003E c.Real)\r\n\r\n### Fold and Reduce\r\n\r\nMatrices also provide column/row fold and reduce routines:\r\n\r\n* **FoldByRow(f,state,zeros)**: fold through the values of each row, returns an column-array.\r\n* **FoldRows(f,state)**: fold over all row vectors, returns a row vector.\r\n* **ReduceRows(f)**: reduce all row vectors, returns a row vector.\r\n\r\n\r\nPrinting and Strings\r\n--------------------\r\n\r\nMatrices and vectors try to print themselves to a string with the \u0060ToString\u0060\r\nin a reasonable way, without overflowing the output device on a large matrix.\r\n\r\nNote that this function is not intended to export a data structure to a string or\r\nfile, but to give an informative summary about it. For data import/export,\r\nuse one of the MathNet.Numerics.Data packages instead.\r\n\r\nSome matrix examples:\r\n\r\n [lang=text]\r\n // Matrix\u003Cdouble\u003E.Build.Dense(3,4,(i,j) =\u003E i*10*j).ToString()\r\n DenseMatrix 3x4-Double\r\n 0 0 0 0\r\n 0 10 20 30\r\n 0 20 40 60\r\n\r\n // Matrix\u003Cdouble\u003E.Build.Dense(100,100,(i,j) =\u003E i*10*j).ToString()\r\n DenseMatrix 100x100-Double\r\n 0 0 0 0 0 0 0 0 0 0 0 .. 0 0\r\n 0 10 20 30 40 50 60 70 80 90 100 .. 980 990\r\n 0 20 40 60 80 100 120 140 160 180 200 .. 1960 1980\r\n 0 30 60 90 120 150 180 210 240 270 300 .. 2940 2970\r\n 0 40 80 120 160 200 240 280 320 360 400 .. 3920 3960\r\n 0 50 100 150 200 250 300 350 400 450 500 .. 4900 4950\r\n 0 60 120 180 240 300 360 420 480 540 600 .. 5880 5940\r\n 0 70 140 210 280 350 420 490 560 630 700 .. 6860 6930\r\n .. .. .. .. .. .. .. .. .. .. .. .. .. ..\r\n 0 960 1920 2880 3840 4800 5760 6720 7680 8640 9600 .. 94080 95040\r\n 0 970 1940 2910 3880 4850 5820 6790 7760 8730 9700 .. 95060 96030\r\n 0 980 1960 2940 3920 4900 5880 6860 7840 8820 9800 .. 96040 97020\r\n 0 990 1980 2970 3960 4950 5940 6930 7920 8910 9900 .. 97020 98010\r\n\r\n // Matrix\u003Cdouble\u003E.Build.Random(4,4).ToString()\r\n DenseMatrix 4x4-Double\r\n 1.6286 -1.1126 1.95526 0.950545\r\n 0.537503 -0.465534 2.00984 1.90885\r\n -1.62816 1.04109 -2.06876 0.812197\r\n 0.452355 -0.689394 -0.277921 2.72224\r\n\r\n // Matrix\u003Cdouble\u003E.Build.SparseOfIndexed(4,100,new[] {Tuple.Create(1,2,3.0)})\r\n SparseMatrix 4x100-Double 0.25% Filled\r\n 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .. 0 0\r\n 0 0 3.5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .. 0 0\r\n 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .. 0 0\r\n 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .. 0 0\r\n\r\nVectors are printed as a column that can wrap over to multiple columns if needed:\r\n\r\n [lang=text]\r\n // Vector\u003Cdouble\u003E.Build.Random(15).ToString()\r\n DenseVector 15-Double\r\n 0.519184 0.0950414\r\n 1.65913 2.56783\r\n 0.743408 0.574037\r\n -1.73394 \r\n -0.906662 \r\n 0.853759 \r\n -0.162181 \r\n -0.231667 \r\n -1.26393 \r\n -0.434873 \r\n 0.693421 \r\n -0.513683 \r\n\r\n // Vector\u003Cdouble\u003E.Build.Dense(500,i =\u003E i).ToString()\r\n DenseVector 500-Double\r\n 0 12 24 36 48 60 72 84 96 108 120 132 144 156 168 180 192\r\n 1 13 25 37 49 61 73 85 97 109 121 133 145 157 169 181 193\r\n 2 14 26 38 50 62 74 86 98 110 122 134 146 158 170 182 194\r\n 3 15 27 39 51 63 75 87 99 111 123 135 147 159 171 183 195\r\n 4 16 28 40 52 64 76 88 100 112 124 136 148 160 172 184 196\r\n 5 17 29 41 53 65 77 89 101 113 125 137 149 161 173 185 197\r\n 6 18 30 42 54 66 78 90 102 114 126 138 150 162 174 186 198\r\n 7 19 31 43 55 67 79 91 103 115 127 139 151 163 175 187 199\r\n 8 20 32 44 56 68 80 92 104 116 128 140 152 164 176 188 ..\r\n 9 21 33 45 57 69 81 93 105 117 129 141 153 165 177 189 ..\r\n 10 22 34 46 58 70 82 94 106 118 130 142 154 166 178 190 498\r\n 11 23 35 47 59 71 83 95 107 119 131 143 155 167 179 191 499\r\n\r\nThe format is customizable to some degree, for example we can choose the\r\nfloating point format and culture, or how many rows or columns should be shown:\r\n\r\n [lang=text]\r\n // var m = Matrix\u003Cdouble\u003E.Build.Random(5,100,42); // 42 = random seed\r\n \r\n // m.ToString()\r\n DenseMatrix 5x100-Double\r\n 0.408388 -0.847291 -0.320552 0.162242 2.46434 .. 0.180466 -0.278793\r\n -1.06988 0.063008 -0.527378 1.40716 -0.5962 .. -0.622447 -0.488186\r\n -0.734176 -0.703003 1.33158 0.286498 1.44158 .. -0.834335 -0.0756724\r\n 1.78532 0.020217 1.94275 -0.742821 -0.790251 .. 1.52823 2.49427\r\n -0.660645 1.28166 -1.71351 -1.33282 -0.328162 .. 0.110989 0.252272\r\n\r\n // m.ToString(\u0022G2\u0022, CultureInfo.GetCultureInfo(\u0022de-DE\u0022))\r\n DenseMatrix 5x100-Double\r\n 0,41 -0,85 -0,32 0,16 2,5 -0,77 0,12 0,58 .. 0,18 -0,28\r\n -1,1 0,063 -0,53 1,4 -0,6 -2,8 -0,35 0,3 .. -0,62 -0,49\r\n -0,73 -0,7 1,3 0,29 1,4 -0,00022 -0,3 0,51 .. -0,83 -0,076\r\n 1,8 0,02 1,9 -0,74 -0,79 0,088 0,78 -0,94 .. 1,5 2,5\r\n -0,66 1,3 -1,7 -1,3 -0,33 -0,69 -0,27 -0,68 .. 0,11 0,25\r\n\r\n // m.ToString(3,5) // max 3 rows, 5 columns\r\n DenseMatrix 5x100-Double\r\n 0.408388 -0.847291 -0.320552 .. 0.180466 -0.278793\r\n -1.06988 0.063008 -0.527378 .. -0.622447 -0.488186\r\n -0.734176 -0.703003 1.33158 .. -0.834335 -0.0756724\r\n .. .. .. .. .. ..\r\n\r\n // Matrix\u003Cdouble\u003E.Build.Random(100,100,42)\r\n // .ToMatrixString(2,4,3,4,\u0022=\u0022,\u0022||\u0022,@\u0022\\\\\u0022,\u0022 \u0022,Environment.NewLine,x=\u003Ex.ToString(\u0022G2\u0022))\r\n 0.41 0.36 0.29 = 0.43 0.56 -0.56 0.98\r\n -1.1 -0.64 0.9 = 0.49 -0.3 2 -0.5\r\n || || || \\\\ || || || ||\r\n -0.87 -2.2 0.79 = 0.96 1.8 1.4 0.067\r\n -0.14 -0.016 -0.55 = -0.36 0.33 0.24 0.52\r\n -1.3 -1 -0.81 = 1.3 1 -1.1 -0.28\r\n -0.21 -1.7 2.6 = -1.5 -1.2 -0.0014 3.4\r\n\r\nIf you are using Math.NET Numerics from within F# interactive, you may want\r\nto load the MathNet.Numerics.fsx script of the F# package. Besides loading\r\nthe assemblies it also adds proper FSI printers for both matrices and vectors.\r\n"},{"uri":"https://numerics.mathdotnet.com/MatrixMarket.html","title":"NIST MatrixMarket Text Files\r\n","content":"NIST MatrixMarket Text Files\r\n============================\r\n\r\nMatrixMarket is both a [vast repository of test data](https://math.nist.gov/MatrixMarket/)\r\nand a text-based [exchange file format](https://math.nist.gov/MatrixMarket/formats.html) provided by NIST.\r\nBeing text-based makes it convenient to deal with and program against, and also works well with versioning\r\ntools like [Git](https://www.git-scm.com/). But other than [CSV](CSV.html) it can also store sparse matrices in a compact way.\r\n\r\nMath.NET Numerics provides basic support for MatrixMarket files with the **MathNet.Numerics.Data.Text** package,\r\nwhich is available on NuGet as separate package and not included in the basic distribution.\r\n\r\n\r\nReading a matrix from a MatrixMarket file\r\n-----------------------------------------\r\n\r\nThe \u0060MatrixMarketReader\u0060 class provides static functions to read a matrix or a vector from a file or string.\r\nIt can read from:\r\n\r\n* **TextReader**: If you have your delimited data already in memory in a string,\r\n you can use this method using a StringReader.\r\n* **Stream**: read directly from a stream, e.g. a MemoryStream, FileStream or NetworkStream.\r\n* **File Path (string)**: read from a file, specified by the file system path. Optionally GZip compressed.\r\n\r\nAll these functions expect the data type of the matrix to be generated as generic type argument.\r\nOnly Double, Single, Complex and Complex32 are supported.\r\n\r\nExample:\r\n\r\n [lang=csharp]\r\n using MathNet.Numerics.Data.Text;\r\n\r\n Matrix\u003Cdouble\u003E matrix = MatrixMarketReader.ReadMatrix\u003Cdouble\u003E(\u0022fidap007.mtx\u0022);\r\n\r\n\r\nWriting a matrix to a MatrixMarket file\r\n---------------------------------------\r\n\r\nThe dual to the reader above is the \u0060MatrixMarketWriter\u0060 class that can serialize a matrix or vector\r\nto a MatrixMarket text file, stream or TextWriter.\r\n\r\nExample:\r\n\r\n [lang=csharp]\r\n MatrixMarketWriter.WriteMatrix(\u0022matrix.mtx\u0022, m);\r\n\r\n\r\nAlternatives\r\n------------\r\n\r\nThe data extension packages also offer other ways to serialize a matrix to a binary stream or file.\r\nAmong others:\r\n\r\n* [Delimited Text Files (CSV \u0026 TSV)](CSV.html)\r\n* [MATLAB Level-5 Mat files](MatlabFiles.html)\r\n"},{"uri":"https://numerics.mathdotnet.com/MKL.html","title":"Intel Math Kernel Library (MKL)\r\n","content":"Intel Math Kernel Library (MKL)\r\n===============================\r\n\r\nMath.NET Numerics is designed such that performance-sensitive algorithms\r\ncan be swapped with alternative implementations by the concept of providers.\r\nThere is currently only a provider for [linear algebra related routines](https://numerics.mathdotnet.com/api/MathNet.Numerics.Providers.LinearAlgebra.Mkl/MklLinearAlgebraProvider.htm), but there\r\nare plans to add additional more e.g. related to nonlinear optimization problems or signal processing.\r\n\r\nProviders become interesting when they can leverage a platform-native high performance library\r\nlike Intel MKL instead of the default purely managed provider. Math.NET Numerics\r\nprovides such a provider as NuGet packages:\r\n\r\n* MathNet.Numerics.MKL.Win\r\n* MathNet.Numerics.MKL.Linux\r\n\r\nSince these native libraries can become very big, there are also variants supporting\r\nonly a single platform, for example:\r\n\r\n* MathNet.Numerics.MKL.Win-x86\r\n* MathNet.Numerics.MKL.Win-x64\r\n\r\nIn order to leverage the MKL linear algebra provider, we need to make sure the .NET\r\nruntime can find the native libraries (see below) and then enable it by calling:\r\n\r\n [lang=csharp]\r\n Control.UseNativeMKL();\r\n\r\nAlternatively you can also enable it by setting the environment variable \u0060MathNetNumericsLAProvider=MKL\u0060.\r\n\r\nYou can also explicitly disable the MKL provider by forcing it to use the managed provider by calling:\r\n\r\n [lang=csharp]\r\n Control.UseManaged();\r\n\r\nYou can tell what provider is effectively loaded by calling \u0060Control.LinearAlgebraProvider.ToString()\u0060,\r\nwhich will return something along the lines of \u0060Intel MKL (x86; revision 7)\u0060.\r\n\r\n\r\nNative Binaries\r\n---------------\r\n\r\nIn .Net, the fusion engine is responsible for finding referenced\r\nassemblies in the file system and loading them into the executing process.\r\nHowever, native binaries like our MKL provider are platform specific,\r\nso we need to load them with services of the platform instead of the .Net runtime.\r\nWe use P/Invoke to talk to the binaries, but for this to work they must\r\nhave already been loaded or the platform service needs to be able to find and\r\nload them on its own.\r\n\r\nIn order to make providers easier to use, since v3.6.0 Math.NET Numerics\r\nfirst tries to load native providers from a set of known directories before\r\nfalling back to the platform\u0027s default behavior. In each of these directories\r\nit first looks for a processor-architecture specific folder within the directory,\r\nbefore looking at the directory itself:\r\n\r\n1. If \u0060Control.NativeProviderPath\u0060 is set: \u0060{NativeProviderPath}/{Platform}/\u0060\r\n2. If \u0060Control.NativeProviderPath\u0060 is set: \u0060{NativeProviderPath}/\u0060\r\n3. \u0060{AppDomain.BaseDirectory}/{Platform}/\u0060\r\n4. \u0060{AppDomain.BaseDirectory}/\u0060\r\n5. \u0060{ExecutingAssemblyPath}/{Platform}/\u0060\r\n6. \u0060{ExecutingAssemblyPath}/\u0060\r\n7. Fall back to the platform\u0027s default behavior (see below)\r\n\r\nWhere \u0060{Platform}\u0060 can be one of the following: \u0060x86\u0060, \u0060x64\u0060, \u0060ia64\u0060, \u0060arm\u0060 or \u0060arm64\u0060.\r\n\r\nThis means that you can, for example, place the 32 bit MKL provider binaries into \u0060C:\\MKL\\x86\u0060\r\nand the 64 bit ones into \u0060C:\\MKL\\x64\u0060, and then set \u0060Control.NativeProviderPath = @\u0022C:\\MKL\u0022;\u0060.\r\nNumerics will automatically choose the right one depending on whether your process is\r\nrunning in 32 or 64 bit mode, and there is no more need to copy the large binaries to the\r\noutput folder of every script or project.\r\n\r\n\r\nDefault Behavior on Windows\r\n---------------------------\r\n\r\nOn Windows it is usually enough to make sure the native libraries are in the\r\nsame folder as the executable. Reference the appropriate NuGet package and set\r\n\u0022Copy to Output Directory\u0022 for both MathNet.Numerics.MKL.dll and libiomp5md.dll\r\nto \u0022Copy always\u0022, or place the two native DLLs manually into the same directory\r\nas your application\u0027s executable. There is no need to set the native provider\r\npath explicitly.\r\n\r\nFor more details how the platform default behavior works and what influences it,\r\nsee [Dynamic-Link Library Search Order](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682586.aspx).\r\n\r\n\r\nDefault Behavior on Linux\r\n-------------------------\r\n\r\nNative assembly resolving is very different on Linux than on Windows, simply putting the native\r\nlibraries into the same folder as the executable is not enough. The safe way is to edit \u0060/etc/ld.so.conf\u0060\r\nand use \u0060ldconfig\u0060 to tell where to look for the libraries. Alternatively you could add the path\r\nto \u0060LD_LIBRARY_PATH\u0060 or even just copy them to \u0060/usr/lib\u0060.\r\n\r\nFor details see Mono\u0027s [Interop with Native Libraries](https://www.mono-project.com/docs/advanced/pinvoke/#linux-shared-library-search-path).\r\n\r\n\r\nDefault Behavior on Mac OS X\r\n----------------------------\r\n\r\nYou can configure the search path on one of the environment variables like \u0060DYLD_LIBRARY_PATH\u0060\r\nor just copy them e.g. to \u0060/usr/lib\u0060.\r\n\r\nFor details see Mono\u0027s [Interop with Native Libraries](https://www.mono-project.com/docs/advanced/pinvoke/#mac-os-x-framework-and-dylib-search-path).\r\n\r\nTo build the MKL native provider for OSX:\r\n\r\n1. Make sure you\u0027ve a valid [Intel MKL](https://software.intel.com/en-us/qualify-for-free-software/academicresearcher) licence installed on your mac (look at opt/intel).\r\n If not, you can get a free trial on intel\u0027s web site.\r\n2. Open the terminal\r\n3. cd to the folder mathnet-numerics/src/NativeProviders/OSX\r\n4. Run the .sh script by typing sh mkl_build.sh\r\n5. ... wait for the build\r\n\r\n\r\n [lang=sh]\r\n lionel:~ Lionel$ cd /Users/Lionel/Public/Git/GitHub/mathnet-numerics/src/NativeProviders/OSX\r\n lionel:OSX Lionel$ ls\r\n mkl_build.sh\r\n lionel:OSX Lionel$ sh mkl_build.sh\r\n\r\nCheck the /x86 and /x64 folders in mathnet-numerics/out/MKL: you should now find the \u0060libiomp5.dylib\u0060 and \u0060MathNet.Numerics.MKL.dll\u0060 libaries.\r\nYou need to add the path to the generated libraries in your \u0060DYLD_LIBRARY_PATH\u0060 environment variable (which you can move to the folder of you choice before).\r\nTo do that, open your /Users/Lionel/.bas_profile.sh file with a text editor and add the following statements.\r\n\r\n\t[lang=sh]\r\n export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/Users/Lionel/../mathnet-numerics/out/MKL/OSX/x64\r\n export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/Users/Lionel/../mathnet-numerics/out/MKL/OSX/x86\r\n\r\nOf course replace \u0060Lionel\u0060 by your account login.\r\n\r\nHave a look a the example down this page to compare MKL-provider vs. managed-provider performances.\r\n\r\n\r\nF# Interactive\r\n--------------\r\n\r\nIn F# Interactive, the easiest way to use native providers is to copy them to a shared\r\ndirectory somewhere and use them directly from there:\r\n\r\n [lang=fsharp]\r\n Control.NativeProviderPath \u003C- @\u0022C:\\MKL\u0022\r\n Control.UseNativeMKL()\r\n\r\nIf you are using the F# Power Tools in VisualStudio, you can also let it generate \u0022Reference\r\nscripts for F# Interactive\u0022 right from the context menu. This will generate a script called\r\n\u0060load-references.fsx\u0060 in a \u0060Scripts\u0060 folder, which you can extend as follows to load the\r\nMKL provider automatically.\r\n\r\n [lang=fsharp]\r\n open System.IO\r\n open MathNet.Numerics\r\n\r\n Control.NativeProviderPath \u003C- Path.Combine(__SOURCE_DIRECTORY__,\u0022../\u0022)\r\n Control.UseNativeMKL()\r\n\r\nThis script assumes that the MKL binaries have been copied to the project directory,\r\nwhich is also where the NuGet packages place them by default. If you place them somewhere\r\nelse, adapt the path accordingly.\r\n\r\nSee also [Loading Native DLLs in F# Interactive](https://christoph.ruegg.name/blog/loading-native-dlls-in-fsharp-interactive.html)\r\nfor more alternatives.\r\n\r\nLINQPad and assembly shadowing\r\n------------------------------\r\n\r\nThe automatic strategy may still work if assembly shadowing is involved,\r\nbut it often simpler and more reliable to provide the folder explicitly.\r\nThis also works well in LINQPad, with and without assembly shadowing:\r\n\r\n [lang=csharp]\r\n Control.NativeProviderPath = @\u0022C:\\MKL\u0022;\r\n Control.UseNativeMKL();\r\n\r\n\r\nExample: Intel MKL on Linux with Mono\r\n-------------------------------------\r\n\r\nWe also provide MKL NuGet package for Linux if you do not want to build them yourself. Assuming you have\r\nMono and NuGet installed (here v3.2.8), you can fetch the MKL package of the right architecture\r\n(x64 or x86, \u0060uname -m\u0060 if you don\u0027t know) as usual:\r\n\r\n [lang=sh]\r\n mono nuget.exe install MathNet.Numerics -Pre -OutputDirectory packages\r\n mono nuget.exe install MathNet.Numerics.MKL.Linux-x64 -Pre -OutputDirectory packages\r\n\r\nNative assembly resolving is very different on Linux than on Windows, simply putting the native\r\nlibraries into the same folder as the executable is not enough. The safe way is to edit \u0060/etc/ld.so.conf\u0060\r\nand use \u0060ldconfig\u0060 to tell where to look for the libraries, but for now we\u0027ll just copy them to \u0060/usr/lib\u0060:\r\n\r\n [lang=sh]\r\n sudo cp packages/MathNet.Numerics.MKL.Linux-x64.1.3.0/content/libiomp5.so /usr/lib/\r\n sudo cp packages/MathNet.Numerics.MKL.Linux-x64.1.3.0/content/MathNet.Numerics.MKL.dll /usr/lib/\r\n\r\nThen we\u0027re all set and can just call \u0060Control.UseNativeMKL()\u0060 if we want to use the native provider.\r\nLet\u0027s create the following C# file \u0060Example.cs\u0060:\r\n\r\n [lang=csharp]\r\n using System;\r\n using System.Diagnostics;\r\n using MathNet.Numerics;\r\n using MathNet.Numerics.LinearAlgebra;\r\n\r\n class Program\r\n {\r\n static void Main(string[] args)\r\n {\r\n // Using managed code only\r\n Control.UseManaged();\r\n Console.WriteLine(Control.LinearAlgebraProvider);\r\n\r\n var m = Matrix\u003Cdouble\u003E.Build.Random(500, 500);\r\n var v = Vector\u003Cdouble\u003E.Build.Random(500);\r\n\r\n var w = Stopwatch.StartNew();\r\n var y1 = m.Solve(v);\r\n Console.WriteLine(w.Elapsed);\r\n Console.WriteLine(y1);\r\n\r\n // Using the Intel MKL native provider\r\n Control.UseNativeMKL();\r\n Console.WriteLine(Control.LinearAlgebraProvider);\r\n\r\n w.Restart();\r\n var y2 = m.Solve(v);\r\n Console.WriteLine(w.Elapsed);\r\n Console.WriteLine(y2);\r\n }\r\n }\r\n\r\nCompile and run:\r\n\r\n [lang=sh]\r\n # single line:\r\n mcs -optimize -lib:packages/MathNet.Numerics.3.0.0-alpha8/lib/net40/\r\n -r:MathNet.Numerics.dll Example.cs -out:Example\r\n # launch:\r\n mono Example\r\n\r\n\r\nLicensing Restrictions\r\n----------------------\r\n\r\nBe aware that unlike the core of Math.NET Numerics including the native wrapper, which are both\r\nopen source under the terms of the MIT/X11 license, the Intel MKL binaries themselves are closed\r\nsource and non-free.\r\n\r\nThe Math.NET Numerics project does own an Intel MKL license (for Windows, no longer for Linux) and\r\nthus does have the right to distribute it along Math.NET Numerics. You can therefore use the Math.NET\r\nNumerics MKL native provider for free for your own use. However, it does *not* give you any right to\r\nredistribute it again yourself to customers of your own product. **If you need to redistribute,\r\nbuy a license from Intel. If unsure, contact the Intel sales team to clarify.**\r\n"},{"uri":"https://numerics.mathdotnet.com/Packages.html","title":"NuGet Packages \u0026amp; Binaries\r\n","content":"NuGet Packages \u0026 Binaries\r\n=========================\r\n\r\nThe recommended way to get Math.NET Numerics is NuGet. The following packages are\r\nprovided and maintained in the public [NuGet Gallery](https://nuget.org/profiles/mathnet/).\r\nThe complete set of Zip and NuGet packages including symbol packages is also available in the\r\n[release archive](https://archive.mathdotnet.com/Math.NET%20Numerics/).\r\n\r\n\r\nMath.NET Numerics\r\n-----------------\r\n\r\nIn most scenarios you\u0027ll only need the primary package named \u0060MathNet.Numerics\u0060.\r\nIf you are working with F# we recommend to also use the F# extension package\r\nfor a more natural and idiomatic experience.\r\n\r\n[MathNet.NET Numerics Release Notes](ReleaseNotes.html)\r\n\r\n- [**MathNet.Numerics**](https://www.nuget.org/packages/MathNet.Numerics/) - core package, including .Net 4.0, .Net Standard 1.3 and higher.\r\n- [**MathNet.Numerics.FSharp**](https://www.nuget.org/packages/MathNet.Numerics.FSharp/) - optional extensions for a better F# experience. BigRational.\r\n\r\nBoth packages above do not have a strong name. While we do not recommend it,\r\nthere are valid scenarios where strong named assemblies are required. That\u0027s why\r\nwe also provide strong-named variants with the \u0060.Signed\u0060 suffix. Note that signed\r\npackages do not contain portable builds.\r\n\r\n- [**MathNet.Numerics.Signed**](https://www.nuget.org/packages/MathNet.Numerics.Signed/) - strong-named version of the core package.\r\n- [**MathNet.Numerics.FSharp.Signed**](https://www.nuget.org/packages/MathNet.Numerics.FSharp.Signed/) - strong-named version of the F# package.\r\n\r\nIntel MKL Native Provider\r\n-------------------------\r\n\r\nThe new combined package includes both 32 and 64 bit binaries and can automatically\r\npick the right one at runtime. It is also MsBuild integrated, so there is no\r\nmore need to any manual file handling. But it is only supported by Math.NET Numerics\r\nv3.6.0 and higher.\r\n\r\nIf you intend to [maintain the native binaries manually](MKL.html#Native-Binaries)\r\nit may be easier to download the Zip file in the [release archive](https://archive.mathdotnet.com/Math.NET%20Numerics/Zip/).\r\n\r\n[Intel MKL Native Provider Release Notes](ReleaseNotes-MKL.html)\r\n\r\n- [**MathNet.Numerics.MKL.Win**](https://www.nuget.org/packages/MathNet.Numerics.MKL.Win/) - Windows (combined, MsBuild integrated).\r\n- [**MathNet.Numerics.MKL.Win-x64**](https://www.nuget.org/packages/MathNet.Numerics.MKL.Win-x64/) - Windows 64-bit only.\r\n- [**MathNet.Numerics.MKL.Win-x86**](https://www.nuget.org/packages/MathNet.Numerics.MKL.Win-x86/) - Windows 32-bit only.\r\n- [**MathNet.Numerics.MKL.Linux-x64**](https://www.nuget.org/packages/MathNet.Numerics.MKL.Linux-x64/) - Linux 64-bit.\r\n- [**MathNet.Numerics.MKL.Linux-x86**](https://www.nuget.org/packages/MathNet.Numerics.MKL.Linux-x86/) - Linux 32-bit.\r\n\r\nData Extensions\r\n---------------\r\n\r\nData/IO Packages for reading and writing data.\r\n\r\n[Data Extensions Release Notes](ReleaseNotes-Data.html)\r\n\r\n- [**MathNet.Numerics.Data.Text**](https://www.nuget.org/packages/MathNet.Numerics.Data.Text/) - Text-based matrix formats like [CSV](CSV.html) and [MatrixMarket](MatrixMarket.html).\r\n- [**MathNet.Numerics.Data.Matlab**](https://www.nuget.org/packages/MathNet.Numerics.Data.Matlab/) - [MATLAB Level-5](MatlabFiles.html) matrix file format.\r\n"},{"uri":"https://numerics.mathdotnet.com/Probability.html","title":"Probability Distributions\r\n","content":" [hide]\r\n #I \u0022../../out/lib/net40\u0022\r\n #r \u0022MathNet.Numerics.dll\u0022\r\n #r \u0022MathNet.Numerics.FSharp.dll\u0022\r\n open System.Numerics\r\n open MathNet.Numerics\r\n open MathNet.Numerics.Random\r\n open MathNet.Numerics.Distributions\r\n\r\nProbability Distributions\r\n=========================\r\n\r\nMath.NET Numerics provides a wide range of probability distributions. Given the\r\ndistribution parameters they can be used to investigate their statistical properties\r\nor to sample non-uniform random numbers.\r\n\r\nAll the distributions implement a common set of operations such as\r\nevaluating the density (PDF) and the cumulative distribution (CDF)\r\nat a given point, or to compute the mean, standard deviation and other properties.\r\nBecause it is often numerically more stable and faster to compute such statistical quantities\r\nin the logarithmic domain, we also provide a selection of them in the log domain with the \u0022Ln\u0022 suffix,\r\ne.g. DensityLn for the logarithmic density.\r\n\r\n [lang=csharp]\r\n using MathNet.Numerics.Distributions;\r\n using MathNet.Numerics.Random;\r\n\r\n // create a parametrized distribution instance\r\n var gamma = new Gamma(2.0, 1.5);\r\n\r\n // distribution properties\r\n double mean = gamma.Mean;\r\n double variance = gamma.Variance;\r\n double entropy = gamma.Entropy;\r\n\r\n // distribution functions\r\n double a = gamma.Density(2.3); // PDF\r\n double b = gamma.DensityLn(2.3); // ln(PDF)\r\n double c = gamma.CumulativeDistribution(0.7); // CDF\r\n\r\n // non-uniform number sampling\r\n double randomSample = gamma.Sample();\r\n\r\nBoth probability functions and sampling are also available as static functions\r\nfor simpler usage scenarios:\r\n\r\n [lang=csharp]\r\n // distribution parameters must be passed as arguments\r\n double a2 = Gamma.PDF(2.0, 1.5, 2.3);\r\n double randomSample2 = Gamma.Sample(2.0, 1.5);\r\n\r\n\u003Cdiv style=\u0022overflow:auto;\u0022\u003E\r\n\u003Cdiv style=\u0022float: left; width: 50%;\u0022\u003E\r\n\r\n### Continuous Distributions\r\n\r\n* [Continuous Uniform](https://en.wikipedia.org/wiki/Uniform_distribution_%28continuous%29)\r\n* [Normal](https://en.wikipedia.org/wiki/Normal_distribution)\r\n* [Log Normal](https://en.wikipedia.org/wiki/Log-normal_distribution)\r\n* [Beta](https://en.wikipedia.org/wiki/Beta_distribution)\r\n* [Cauchy](https://en.wikipedia.org/wiki/cauchy_distribution) (Cauchy-Lorentz)\r\n* [Chi](https://en.wikipedia.org/wiki/Chi_distribution)\r\n* [Chi Squared](https://en.wikipedia.org/wiki/Chi-square_distribution)\r\n* [Erlang](https://en.wikipedia.org/wiki/Erlang_distribution)\r\n* [Exponential](https://en.wikipedia.org/wiki/exponential_distribution)\r\n* [Fisher-Snedecor](https://en.wikipedia.org/wiki/F-distribution) (F-Distribution)\r\n* [Gamma](https://en.wikipedia.org/wiki/Gamma_distribution)\r\n* [Inverse Gamma](https://en.wikipedia.org/wiki/inverse-gamma_distribution)\r\n* [Laplace](https://en.wikipedia.org/wiki/Laplace_distribution)\r\n* [Pareto](https://en.wikipedia.org/wiki/Pareto_distribution)\r\n* [Rayleigh](https://en.wikipedia.org/wiki/Rayleigh_distribution)\r\n* [Stable](https://en.wikipedia.org/wiki/Stable_distribution)\r\n* [Student-T](https://en.wikipedia.org/wiki/Student%27s_t-distribution)\r\n* [Weibull](https://en.wikipedia.org/wiki/Weibull_distribution)\r\n* [Triangular](https://en.wikipedia.org/wiki/Triangular_distribution)\r\n\r\n\u003C/div\u003E\r\n\u003Cdiv style=\u0022float: right; width: 50%;\u0022\u003E\r\n\r\n### Discrete Distributions\r\n\r\n* [Discrete Uniform](https://en.wikipedia.org/wiki/Uniform_distribution_%28discrete%29)\r\n* [Bernoulli](https://en.wikipedia.org/wiki/Bernoulli_distribution)\r\n* [Binomial](https://en.wikipedia.org/wiki/Binomial_distribution)\r\n* [Negative Binomial](https://en.wikipedia.org/wiki/Negative_binomial_distribution)\r\n* [Geometric](https://en.wikipedia.org/wiki/geometric_distribution)\r\n* [Hypergeometric](https://en.wikipedia.org/wiki/Hypergeometric_distribution)\r\n* [Poisson](https://en.wikipedia.org/wiki/Poisson_distribution)\r\n* [Categorical](https://en.wikipedia.org/wiki/Categorical_distribution)\r\n* [Conway-Maxwell-Poisson](https://en.wikipedia.org/wiki/Conway%E2%80%93Maxwell%E2%80%93Poisson_distribution)\r\n* [Zipf](https://en.wikipedia.org/wiki/Zipf%27s_law)\r\n\r\n### Multivariate Distributions\r\n\r\n* [Dirichlet](https://en.wikipedia.org/wiki/Dirichlet_distribution)\r\n* [Inverse Wishart](https://en.wikipedia.org/wiki/Inverse-Wishart_distribution)\r\n* [Matrix Normal](https://en.wikipedia.org/wiki/Matrix_normal_distribution)\r\n* [Multinomial](https://en.wikipedia.org/wiki/Multinomial_distribution)\r\n* [Normal Gamma](https://en.wikipedia.org/wiki/Normal-gamma_distribution)\r\n* [Wishart](https://en.wikipedia.org/wiki/Wishart_distribution)\r\n\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\r\n\r\nDistribution Parameters\r\n-----------------------\r\n\r\nThere are many ways to parametrize a distribution in the literature. When using the\r\ndefault constructor, read carefully which parameters it requires. For distributions where\r\nmultiple ways are common there are also static methods, so you can use the one that fits best.\r\nFor example, a normal distribution is usually parametrized with mean and standard deviation,\r\nbut if you\u0027d rather use mean and precision:\r\n\r\n [lang=csharp]\r\n var normal = Normal.WithMeanPrecision(0.0, 0.5);\r\n\r\nSince probability distributions can also be sampled to generate random numbers\r\nwith the configured distribution, all constructors optionally accept a random generator\r\nas last argument.\r\n\r\n [lang=csharp]\r\n var gamma2 = new Gamma(2.0, 1.5, new MersenneTwister());\r\n\r\n // the random generator can also be replaced on an existing instance\r\n gamma2.RandomSource = new Mrg32k3a();\r\n\r\nA few more examples, this time in F#:\r\n\r\n [lang=fsharp]\r\n // some probability distributions\r\n let normal = Normal.WithMeanVariance(3.0, 1.5, a)\r\n let exponential = Exponential(2.4)\r\n let gamma = Gamma(2.0, 1.5, Random.crypto())\r\n let cauchy = Cauchy(0.0, 1.0, Random.mrg32k3aWith 10 false)\r\n let poisson = Poisson(3.0)\r\n let geometric = Geometric(0.8, Random.system())\r\n\r\nSome of the distributions also have routines for maximum-likelihood parameter\r\nestimation from a set of samples:\r\n\r\n [lang=fsharp]\r\n let estimation = LogNormal.Estimate([| 2.0; 1.5; 2.1; 1.2; 3.0; 2.4; 1.8 |])\r\n let mean, variance = estimation.Mean, estimation.Variance\r\n let moreSamples = estimation.Samples() |\u003E Seq.take 10 |\u003E Seq.toArray\r\n\r\nor in C#:\r\n\r\n [lang=csharp]\r\n LogNormal estimation = LogNormal.Estimate(new [] {2.0, 1.5, 2.1, 1.2, 3.0, 2.4, 1.8});\r\n double mean = estimation.Mean, variance = estimation.Variance;\r\n double[] moreSamples = estimation.Samples().Take(10).ToArray();\r\n\r\n\r\nSampling a Probability Distribution\r\n-----------------------------------\r\n\r\nEach distribution provides methods to generate random numbers from that distribution.\r\nThese random variate generators work by accessing the distribution\u0027s member RandomSource\r\nto provide uniform random numbers. By default, this member is an instance of System.Random\r\nbut one can easily replace this with more sophisticated random number generators from\r\n\u0060MathNet.Numerics.Random\u0060 (see [Random Numbers](Random.html) for details).\r\n\r\n [lang=fsharp]\r\n // sample some random numbers from these distributions\r\n // continuous distributions sample to floating-point numbers:\r\n let continuous =\r\n [ yield normal.Sample()\r\n yield exponential.Sample()\r\n yield! gamma.Samples() |\u003E Seq.take 10 ]\r\n\r\n // discrete distributions on the other hand sample to integers:\r\n let discrete =\r\n [ poisson.Sample()\r\n poisson.Sample()\r\n geometric.Sample() ]\r\n\r\nInstead of creating a distribution object we can also sample directly with static functions.\r\nNote that no intermediate value caching is possible this way and parameters must be validated on each call.\r\n\r\n [lang=fsharp]\r\n // using the default number generator (SystemRandomSource.Default)\r\n let w = Rayleigh.Sample(1.5)\r\n let x = Hypergeometric.Sample(100, 20, 5)\r\n\r\n // or by manually providing the uniform random number generator\r\n let u = Normal.Sample(Random.system(), 2.0, 4.0)\r\n let v = Laplace.Samples(Random.mersenneTwister(), 1.0, 3.0) |\u003E Seq.take 100 |\u003E List.ofSeq\r\n\r\nIf you need to sample not just one or two values but a large number of them,\r\nthere are routines that either fill an existing array or return an enumerable.\r\nThe variant that fills an array is generally the fastest. Routines to sample\r\nmore than one value use the plural form \u0060Samples\u0060 instead of \u0060Sample\u0060.\r\n\r\nLet\u0027s sample 100\u0027000 values from a laplace distribution with mean 1.0 and scale 2.0 in C#:\r\n\r\n [lang=csharp]\r\n var samples = new double[100000];\r\n Laplace.Samples(samples, 1.0, 2.0);\r\n\r\nLet\u0027s do some random walks in F# (TODO: Graph):\r\n\r\n [lang=fsharp]\r\n Seq.scan (\u002B) 0.0 (Normal.Samples(0.0, 1.0)) |\u003E Seq.take 10 |\u003E Seq.toArray\r\n Seq.scan (\u002B) 0.0 (Cauchy.Samples(0.0, 1.0)) |\u003E Seq.take 10 |\u003E Seq.toArray\r\n\r\n\r\nDistribution Functions and Properties\r\n-------------------------------------\r\n\r\nDistributions can not just be used to generate non-uniform random samples.\r\nOnce parametrized they can compute a variety of distribution properties\r\nor evaluate distribution functions. Because it is often numerically more stable\r\nand faster to compute and work with such quantities in the logarithmic domain,\r\nsome of them are also available with the \u0060Ln\u0060-suffix.\r\n\r\n [lang=fsharp]\r\n // distribution properties of the gamma we\u0027ve configured above\r\n let gammaStats =\r\n ( gamma.Mean,\r\n gamma.Variance,\r\n gamma.StdDev,\r\n gamma.Entropy,\r\n gamma.Skewness,\r\n gamma.Mode )\r\n\r\n // probability distribution functions of the normal we\u0027ve configured above.\r\n let nd = normal.Density(4.0) (* PDF *)\r\n let ndLn = normal.DensityLn(4.0) (* ln(PDF) *)\r\n let nc = normal.CumulativeDistribution(4.0) (* CDF *)\r\n let nic = normal.InverseCumulativeDistribution(0.7) (* CDF^(-1) *)\r\n\r\n // Distribution functions can also be evaluated without creating an object,\r\n // but then you have to pass in the distribution parameters as first arguments:\r\n let nd2 = Normal.PDF(3.0, sqrt 1.5, 4.0)\r\n let ndLn2 = Normal.PDFLn(3.0, sqrt 1.5, 4.0)\r\n let nc2 = Normal.CDF(3.0, sqrt 1.5, 4.0)\r\n let nic2 = Normal.InvCDF(3.0, sqrt 1.5, 0.7)\r\n\r\n\r\nComposing Distributions\r\n-----------------------\r\n\r\nSpecifically for F# there is also a \u0060Sample\u0060 module that allows a somewhat more functional\r\nview on distribution sampling functions by having the random source passed in as last argument.\r\nThis way they can be composed and transformed arbitrarily if curried:\r\n\r\n [lang=fsharp]\r\n /// Transform a sample from a distribution\r\n let s1 rng = tanh (Sample.normal 2.0 0.5 rng)\r\n\r\n /// But we really want to transform the function, not the resulting sample:\r\n let s1f rng = Sample.map tanh (Sample.normal 2.0 0.5) rng\r\n\r\n /// Exactly the same also works with functions generating full sequences\r\n let s1s rng = Sample.mapSeq tanh (Sample.normalSeq 2.0 0.5) rng\r\n\r\n /// Now with multiple distributions, e.g. their product:\r\n let s2 rng = (Sample.normal 2.0 1.5 rng) * (Sample.cauchy 2.0 0.5 rng)\r\n let s2f rng = Sample.map2 (*) (Sample.normal 2.0 1.5) (Sample.cauchy 2.0 0.5) rng\r\n let s2s rng = Sample.mapSeq2 (*) (Sample.normalSeq 2.0 1.5) (Sample.cauchySeq 2.0 0.5) rng\r\n\r\n // Taking some samples from the composed function\r\n Seq.take 10 (s2s (Random.system())) |\u003E Seq.toArray\r\n"},{"uri":"https://numerics.mathdotnet.com/Random.html","title":"Pseudo-Random Numbers\r\n","content":" [hide]\r\n #I \u0022../../out/lib/net40\u0022\r\n #r \u0022MathNet.Numerics.dll\u0022\r\n #r \u0022MathNet.Numerics.FSharp.dll\u0022\r\n open System.Numerics\r\n open MathNet.Numerics\r\n open MathNet.Numerics.Random\r\n open MathNet.Numerics.Distributions\r\n\r\nPseudo-Random Numbers\r\n=====================\r\n\r\nThe .Net Framework base class library (BCL) includes a pseudo-random number generator\r\nfor non-cryptography use in the form of the \u0060System.Random\u0060 class.\r\nMath.NET Numerics provides a few alternatives with different characteristics\r\nin randomness, bias, sequence length, performance and thread-safety. All these classes\r\ninherit from \u0060System.Random\u0060 so you can use them as a drop-in replacement\r\neven in third-party code.\r\n\r\nAll random number generators (RNG) generate numbers in a uniform\r\ndistribution. In practice you often need to sample random numbers with a different\r\ndistribution, like a Gaussian or Poisson. You can do that with one of our probability\r\ndistribution classes, or in F# also using the \u0060Sample\u0060 module. Once parametrized,\r\nthe distribution classes also provide a variety of other functionality around probability\r\ndistributions, like evaluating statistical distribution properties or functions.\r\n\r\n\r\nInitialization\r\n--------------\r\n\r\nWe need to reference Math.NET Numerics and open the namespaces for\r\nrandom numbers and probability distributions:\r\n\r\n [lang=csharp]\r\n using MathNet.Numerics.Random;\r\n using MathNet.Numerics.Distributions;\r\n\r\n\r\nGenerating Random Numbers\r\n-------------------------\r\n\r\nLet\u0027s sample a few random values from a uniform distributed variable\r\n$X\\sim\\mathcal{U}(0,1)$, such that $0 \\le x \u003C 1$:\r\n\r\n [lang=csharp]\r\n // create an array with 1000 random values\r\n double[] samples = SystemRandomSource.Doubles(1000);\r\n\r\n // now overwrite the existing array with new random values\r\n SystemRandomSource.Doubles(samples);\r\n\r\n // we can also create an infinite sequence of random values:\r\n IEnumerable\u003Cdouble\u003E sampleSeq = SystemRandomSource.DoubleSequence();\r\n\r\n // take a single random value\r\n System.Random rng = SystemRandomSource.Default;\r\n double sample = rng.NextDouble();\r\n decimal sampled = rng.NextDecimal();\r\n\r\nIn F# we can do exactly the same, or alternatively use the \u0060Random\u0060 module:\r\n\r\n [lang=fsharp]\r\n let samples = Random.doubles 1000\r\n\r\n // overwrite the whole array with new random values\r\n Random.doubleFill samples\r\n\r\n // create an infinite sequence:\r\n let sampleSeq = Random.doubleSeq ()\r\n\r\n // take a single random value\r\n let rng = Random.shared\r\n let sample = rng.NextDouble()\r\n let sampled = rng.NextDecimal()\r\n\r\nIf you have used the .Net BCL random number generators before, you have likely\r\nnoticed a few differences: we used special routines to create a full array or\r\nsequence in one go, we were able to sample a decimal number, an we used static functions\r\nand a shared default instance instead of creating our own instance.\r\n\r\nMath.NET Numerics provides a few alternative random number generators in their own types.\r\nFor example, \u0060MersenneTwister\u0060 implements the very popular mersenne twister algorithm. All these types\r\ninherit from \u0060System.Random\u0060, are fully compatible to it and can also be used exactly the same way:\r\n\r\n [lang=csharp]\r\n System.Random random = new SystemRandomSource();\r\n var sample = random.NextDouble();\r\n\r\nHowever, unlike System.Random they can be made thread safe, use much more reasonable\r\ndefault seeds and have some convenient extra routines. The \u0060SystemRandomSource\u0060 class that\r\nwas used above uses System.Random to generate random numbers internally - but with all the extras.\r\n\r\n\r\nFull Range Integers and Decimal\r\n-------------------------------\r\n\r\nOut of the box, \u0060System.Random\u0060 only provides \u0060Next\u0060 methods to sample integers\r\nin the [0, Int.MaxValue) range and \u0060NextDouble\u0060 for floating point numbers in the [0,1) interval.\r\nDid you ever have a need to generate numbers of the full integer range including negative numbers,\r\nor a \u0060System.Decimal\u0060? Extending discrete random numbers to different ranges or types is non-trivial\r\nif the distribution should still be uniform over the chosen range. That\u0027s why we\u0027ve added a few extensions\r\nmethods which are available on all RNGs (including System.Random itself):\r\n\r\n* **NextInt64** generates a 64 bit integer, uniform in the range [0, Long.MaxValue)\r\n* **NextDecimal** generates a \u0060System.Decimal\u0060, uniform in the range [0.0, 1.0)\r\n* **NextFullRangeInt32** generates a 32 bit integer, uniform in the range [Int.MinValue, Int.MaxValue]\r\n* **NextFullRangeInt64** generates a 64 bit integer, uniform in the range [Long.MinValue, Long.MaxValue]\r\n\r\n\r\nSeeds\r\n-----\r\n\r\nAll RNGs can be initialized with a custom seed number. The same seed causes\r\nthe same number sequence to be generated, which can be very useful if you need results\r\nto be reproducible, e.g. in testing/verification. The exception is cryptography,\r\nwhere reproducible random number sequences would be a fatal security flaw,\r\nso our crypto random source does not accept a seed.\r\n\r\nIn the code samples above we did not provide a seed, so a default seed was used.\r\nIf no seed is provided, \u0060System.Random\u0060 uses a time based seed equivalent to the\r\none below. This means that all instances created within a short time-frame\r\n(which typically spans about a thousand CPU clock cycles) will generate\r\nexactly the same sequence. This can happen easily e.g. in parallel computing\r\nand is often unwanted. That\u0027s why all Math.NET Numerics RNGs are by default\r\ninitialized with a robust seed taken from the \u0060CryptoRandomSource\u0060 if available,\r\nor else a combination of a random number from a shared RNG, the time and a Guid\r\n(which are supposed to be generated uniquely, worldwide).\r\n\r\n [lang=fsharp]\r\n let someTimeSeed = RandomSeed.Time() // not recommended\r\n let someGuidSeed = RandomSeed.Guid()\r\n let someRobustSeed = RandomSeed.Robust() // recommended, used by default\r\n\r\nLet\u0027s generate random numbers like before, but this time with custom seed 42:\r\n\r\n [lang=fsharp]\r\n let samplesSeeded = Random.doublesSeed 42 1000\r\n Random.doubleFillSeed 42 samplesSeeded\r\n let samplesSeqSeeded = Random.doubleSeqSeed 42\r\n\r\nOr without the F# Random module, e.g. in C#:\r\n\r\n [lang=csharp]\r\n double[] samplesSeeded = SystemRandomSource.Doubles(1000, 42);\r\n SystemRandomSource.Doubles(samplesSeeded, 42);\r\n IEnumerable\u003Cdouble\u003E sampleSeqSeeded = SystemRandomSource.DoubleSequence(42);\r\n\r\n\r\nUniform Random Number Generators\r\n--------------------------------\r\n\r\nUp to now we\u0027ve used only \u0060SystemRandomSource\u0060, but there\u0027s much more:\r\n\r\n* **SystemRandomSource**: Wraps the .NET System.Random to provide thread-safety\r\n* **CryptoRandomSource**: Wraps the .NET RNGCryptoServiceProvider. *Not available in portable builds.*\r\n* **MersenneTwister**: Mersenne Twister 19937 generator\r\n* **Xorshift**: Multiply-with-carry XOR-shift generator\r\n* **Mcg31m1**: Multiplicative congruential generator using a modulus of 2^31-1 and a multiplier of 1132489760\r\n* **Mcg59**: Multiplicative congruential generator using a modulus of 2^59 and a multiplier of 13^13\r\n* **WH1982**: Wichmann-Hill\u0027s 1982 combined multiplicative congruential generator\r\n* **WH2006**: Wichmann-Hill\u0027s 2006 combined multiplicative congruential generator\r\n* **Mrg32k3a**: 32-bit combined multiple recursive generator with 2 components of order 3\r\n* **Palf**: Parallel Additive Lagged Fibonacci generator\r\n\r\nLet\u0027s sample a few uniform random values using Mersenne Twister in C#:\r\n\r\n [lang=csharp]\r\n // Typical way with an instance:\r\n var random = new MersenneTwister(42); // seed 42\r\n int sampleInt = random.Next();\r\n double sampleDouble = random.NextDouble();\r\n decimal sampleDecimal = random.NextDecimal();\r\n double[] samples = random.NextDoubles(1000);\r\n IEnumerable\u003Cdouble\u003E sampleSeq = random.NextDoubleSequence();\r\n\r\n // Simpler and faster if you need a large sequence, only once:\r\n double[] samples = MersenneTwister.Doubles(1000, 42) // 1000 numbers, seed 42\r\n IEnumerable\u003Cdouble\u003E sampleSeq = MersenneTwister.DoubleSequence(42); // seed 42\r\n\r\nIn F# you can use the constructor as well, or alternatively use the \u0060Random\u0060 module.\r\nIn case of the latter, all objects will be cast to their common base type \u0060System.Random\u0060:\r\n\r\n [lang=fsharp]\r\n // By using the normal constructor (random1 has type MersenneTwister) \r\n let random1 = MersenneTwister()\r\n let random1b = MersenneTwister(42) // with seed\r\n\r\n // By using the Random module (random2 has type System.Random)\r\n let random2 = Random.mersenneTwister ()\r\n let random2b = Random.mersenneTwisterSeed 42 // with seed\r\n let random2c = Random.mersenneTwisterWith 42 false // opt-out of thread-safety\r\n\r\n // Using some other algorithms:\r\n let random3 = Random.crypto ()\r\n let random4 = Random.xorshift ()\r\n let random5 = Random.wh2006 ()\r\n\r\n\r\nShared Instances and Thread Safety\r\n----------------------------------\r\n\r\nGenerators make certain claims about how many random numbers they can generate\r\nuntil the whole sequence repeats itself. However, this only applies if you\r\ncontinue to sample from the same instance and its internal state.\r\nThe generator instances should therefore be reused within an application if long\r\nrandom sequences are needed. If you\u0027d create a new instance each time, the numbers\r\nit generates would be exactly as random as your seed - and thus not very random at all.\r\n\r\nAnother reason to share instances: most generators run an initialization routine before\r\nthey can start generating numbers which can be expensive. Some of them also maintain\r\ntheir internal state in large memory blocks, which can quickly add up when creating multiple\r\ninstances.\r\n\r\nUnfortunately the two generators provided by .NET are not thread-safe and thus cannot be\r\nshared between threads without manual locking. But all the RNGs provided by Math.NET Numerics,\r\nincluding the \u0060SystemRandomSource\u0060 and \u0060CryptoRandomSource\u0060 wrappers, *are* thread-safe by default,\r\nunless explicitly disabled by a constructor argument or by setting \u0060Control.ThreadSafeRandomNumberGenerators\u0060\r\n(which is used if the constructor argument is omitted).\r\n\r\nFor convenience a few generators provide a thread-safe shared instance\r\n\r\n [lang=csharp]\r\n var a = SystemRandomSource.Default;\r\n var b = MersenneTwister.Default;\r\n\r\nOr with the F# module:\r\n\r\n [lang=fsharp]\r\n let a = Random.systemShared\r\n let b = Random.mersenneTwisterShared\r\n\r\n // or if you don\u0027t care, simply\r\n let c = Random.shared;\r\n\r\n\r\nNon-Uniform Random Numbers\r\n--------------------------\r\n\r\nFor non-uniform random number generation you can use the wide range of probability\r\ndistributions in the \u0060MathNet.Numerics.Distributions\u0060 namespace.\r\n\r\n [lang=csharp]\r\n using MathNet.Numerics.Distributions;\r\n\r\n // sample a single value from a standard distribution\r\n double a = Normal.Sample(0.0, 1.0);\r\n\r\n // sample using a custom random number generator\r\n double b = Normal.Sample(new MersenneTwister(), 0.0, 1.0);\r\n\r\n // sample a large number of values in one go\r\n double[] c = new double[100000];\r\n Normal.Samples(c, 0.0, 1.0);\r\n\r\nSee [Probability Distributions](Probability.html) for details.\r\n"},{"uri":"https://numerics.mathdotnet.com/Regression.html","title":"Curve Fitting: Linear Regression\r\n","content":" [hide]\r\n #I \u0022../../out/lib/net40\u0022\r\n #r \u0022MathNet.Numerics.dll\u0022\r\n #r \u0022MathNet.Numerics.FSharp.dll\u0022\r\n open System.Numerics\r\n open MathNet.Numerics\r\n open MathNet.Numerics.LinearRegression\r\n open MathNet.Numerics.LinearAlgebra\r\n\r\nCurve Fitting: Linear Regression\r\n================================\r\n\r\nRegression is all about fitting a low order parametric model or curve to data, so we can\r\nreason about it or make predictions on points not covered by the data. Both data and\r\nmodel are known, but we\u0027d like to find the model parameters that make the model fit best\r\nor good enough to the data according to some metric.\r\n\r\nWe may also be interested in how well the model supports the data or whether we better\r\nlook for another more appropriate model.\r\n\r\nIn a regression, a lot of data is reduced and generalized into a few parameters.\r\nThe resulting model can obviously no longer reproduce all the original data exactly -\r\nif you need the data to be reproduced exactly, have a look at interpolation instead.\r\n\r\n\r\nSimple Regression: Fit to a Line\r\n--------------------------------\r\n\r\nIn the simplest yet still common form of regression we would like to fit a line\r\n$y : x \\mapsto a \u002B b x$ to a set of points $(x_j,y_j)$, where $x_j$ and $y_j$ are scalars.\r\nAssuming we have two double arrays for x and y, we can use \u0060Fit.Line\u0060 to evaluate the $a$ and $b$\r\nparameters of the least squares fit:\r\n\r\n [lang=csharp]\r\n double[] xdata = new double[] { 10, 20, 30 };\r\n double[] ydata = new double[] { 15, 20, 25 };\r\n\r\n Tuple\u003Cdouble, double\u003E p = Fit.Line(xdata, ydata);\r\n double a = p.Item1; // == 10; intercept\r\n double b = p.Item2; // == 0.5; slope\r\n\r\nOr in F#:\r\n\r\n [lang=fsharp]\r\n let a, b = Fit.Line ([|10.0;20.0;30.0|], [|15.0;20.0;25.0|])\r\n\r\nHow well do these parameters fit the data? The data points happen to be positioned\r\nexactly on a line. Indeed, the [coefficient of determination](https://en.wikipedia.org/wiki/Coefficient_of_determination)\r\nconfirms the perfect fit:\r\n\r\n [lang=csharp]\r\n GoodnessOfFit.RSquared(xdata.Select(x =\u003E a\u002Bb*x), ydata); // == 1.0\r\n\r\n\r\nLinear Model\r\n------------\r\n\r\nIn practice, a line is often not an adequate model. But if we can choose a model that is linear,\r\nwe can leverage the power of linear algebra; otherwise we have to resort to iterative methods\r\n(see Nonlinear Optimization).\r\n\r\nA linear model can be described as linear combination of $N$ arbitrary but known\r\nfunctions $f_i(x)$, scaled by the model parameters $p_i$. Note that none of the functions\r\n$f_i$ depends on any of the $p_i$ parameters.\r\n\r\n$$$\r\ny : x \\mapsto p_1 f_1(x) \u002B p_2 f_2(x) \u002B \\cdots \u002B p_N f_N(x)\r\n\r\nIf we have $M$ data points $(x_j,y_j)$, then we can write the regression problem as an\r\noverdefined system of $M$ equations:\r\n\r\n$$$\r\n\\begin{eqnarray}\r\n y_1 \u0026=\u0026 p_1 f_1(x_1) \u002B p_2 f_2(x_1) \u002B \\cdots \u002B p_N f_N(x_1) \\\\\r\n y_2 \u0026=\u0026 p_1 f_1(x_2) \u002B p_2 f_2(x_2) \u002B \\cdots \u002B p_N f_N(x_2) \\\\\r\n \u0026\\vdots\u0026 \\\\\r\n y_M \u0026=\u0026 p_1 f_1(x_M) \u002B p_2 f_2(x_M) \u002B \\cdots \u002B p_N f_N(x_M)\r\n\\end{eqnarray}\r\n\r\nOr in matrix notation with the predictor matrix $X$ and the response $y$:\r\n\r\n$$$\r\n\\begin{eqnarray}\r\n \\mathbf y \u0026=\u0026 \\mathbf X \\mathbf p \\\\\r\n \\begin{bmatrix}y_1\\\\y_2\\\\ \\vdots \\\\y_M\\end{bmatrix} \u0026=\u0026\r\n \\begin{bmatrix}f_1(x_1) \u0026 f_2(x_1) \u0026 \\cdots \u0026 f_N(x_1)\\\\f_1(x_2) \u0026 f_2(x_2) \u0026 \\cdots \u0026 f_N(x_2)\\\\ \\vdots \u0026 \\vdots \u0026 \\ddots \u0026 \\vdots\\\\f_1(x_M) \u0026 f_2(x_M) \u0026 \\cdots \u0026 f_N(x_M)\\end{bmatrix}\r\n \\begin{bmatrix}p_1\\\\p_2\\\\ \\vdots \\\\p_N\\end{bmatrix}\r\n\\end{eqnarray}\r\n\r\nProvided the dataset is small enough, if transformed to the normal equation\r\n$\\mathbf{X}^T\\mathbf y = \\mathbf{X}^T\\mathbf X \\mathbf p$ this can be solved efficiently by the\r\nCholesky decomposition (do not use matrix inversion!).\r\n\r\n [lang=csharp]\r\n Vector\u003Cdouble\u003E p = MultipleRegression.NormalEquations(X, y);\r\n\r\nUsing normal equations is comparably fast as it can dramatically reduce the linear algebra problem\r\nto be solved, but that comes at the cost of less precision. If you need more precision, try using\r\n\u0060MultipleRegression.QR\u0060 or \u0060MultipleRegression.Svd\u0060 instead, with the same arguments.\r\n\r\n\r\nPolynomial Regression\r\n---------------------\r\n\r\nTo fit to a polynomial we can choose the following linear model with $f_i(x) := x^i$:\r\n\r\n$$$\r\ny : x \\mapsto p_0 \u002B p_1 x \u002B p_2 x^2 \u002B \\cdots \u002B p_N x^N\r\n\r\nThe predictor matrix of this model is the [Vandermonde matrix](https://en.wikipedia.org/wiki/Vandermonde_matrix).\r\nThere is a special function in the \u0060Fit\u0060 class for regressions to a polynomial,\r\nbut note that regression to high order polynomials is numerically problematic.\r\n\r\n [lang=csharp]\r\n double[] p = Fit.Polynomial(xdata, ydata, 3); // polynomial of order 3\r\n\r\n\r\nMultiple Regression\r\n-------------------\r\n\r\nThe $x$ in the linear model can also be a vector $\\mathbf x = [x^{(1)}\\; x^{(2)} \\cdots x^{(k)}]$\r\nand the arbitrary functions $f_i(\\mathbf x)$ can accept vectors instead of scalars.\r\n\r\nIf we use $f_i(\\mathbf x) := x^{(i)}$ and add an intercept term $f_0(\\mathbf x) := 1$\r\nwe end up at the simplest form of ordinary multiple regression:\r\n\r\n$$$\r\ny : x \\mapsto p_0 \u002B p_1 x^{(1)} \u002B p_2 x^{(2)} \u002B \\cdots \u002B p_N x^{(N)}\r\n\r\nFor example, for the data points $(\\mathbf{x}_j = [x^{(1)}_j\\; x^{(2)}_j], y_j)$ with values\r\n\u0060([1,4],15)\u0060, \u0060([2,5],20)\u0060 and \u0060([3,2],10)\u0060 we can evaluate the best fitting parameters with:\r\n\r\n [lang=csharp]\r\n double[] p = Fit.MultiDim(\r\n new[] {new[] { 1.0, 4.0 }, new[] { 2.0, 5.0 }, new[] { 3.0, 2.0 }},\r\n new[] { 15.0, 20, 10 },\r\n intercept: true);\r\n\r\nThe \u0060Fit.MultiDim\u0060 routine uses normal equations, but you can always choose to explicitly use e.g.\r\nthe QR decomposition for more precision by using the \u0060MultipleRegression\u0060 class directly:\r\n\r\n [lang=csharp]\r\n double[] p = MultipleRegression.QR(\r\n new[] {new[] { 1.0, 4.0 }, new[] { 2.0, 5.0 }, new[] { 3.0, 2.0 }},\r\n new[] { 15.0, 20, 10 },\r\n intercept: true);\r\n\r\n\r\nArbitrary Linear Combination\r\n----------------------------\r\n\r\nIn multiple regression, the functions $f_i(\\mathbf x)$ can also operate on the whole\r\nvector or mix its components arbitrarily and apply any functions on them, provided they are\r\ndefined at all the data points. For example, let\u0027s have a look at the following complicated but still linear\r\nmodel in two dimensions:\r\n\r\n$$$\r\nz : (x, y) \\mapsto p_0 \u002B p_1 \\mathrm{tanh}(x) \u002B p_2 \\psi(x y) \u002B p_3 x^y\r\n\r\nSince we map (x,y) to (z) we need to organize the tuples in two arrays:\r\n\r\n [lang=csharp]\r\n double[][] xy = new[] { new[]{x1,y1}, new[]{x2,y2}, new[]{x3,y3}, ... };\r\n double[] z = new[] { z1, z2, z3, ... };\r\n\r\nThen we can call Fit.LinearMultiDim with our model, which will return an array with the best fitting 4 parameters $p_0, p_1, p_2, p_3$:\r\n\r\n [lang=csharp]\r\n double[] p = Fit.LinearMultiDim(xy, z,\r\n d =\u003E 1.0, // p0*1.0\r\n d =\u003E Math.Tanh(d[0]), // p1*tanh(x)\r\n d =\u003E SpecialFunctions.DiGamma(d[0]*d[1]), // p2*psi(x*y)\r\n d =\u003E Math.Pow(d[0], d[1])); // p3*x^y\r\n\r\n\r\nEvaluating the model at specific data points\r\n--------------------------------------------\r\n\r\nLet\u0027s say we have the following model:\r\n\r\n$$$\r\ny : x \\mapsto a \u002B b \\ln x\r\n\r\nFor this case we can use the \u0060Fit.LinearCombination\u0060 function:\r\n\r\n [lang=csharp]\r\n double[] p = Fit.LinearCombination(\r\n new[] {61.0, 62.0, 63.0, 65.0},\r\n new[] {3.6,3.8, 4.8, 4.1},\r\n x =\u003E 1.0,\r\n x =\u003E Math.Log(x)); // -34.481, 9.316\r\n\r\nIn order to evaluate the resulting model at specific data points we can manually apply\r\nthe values of p to the model function, or we can use an alternative function with the \u0060Func\u0060\r\nsuffix that returns a function instead of the model parameters. The returned function\r\ncan then be used to evaluate the parametrized model:\r\n\r\n [lang=csharp]\r\n Func\u003Cdouble,double\u003E f = Fit.LinearCombinationFunc(\r\n new[] {61.0, 62.0, 63.0, 65.0},\r\n new[] {3.6, 3.8, 4.8, 4.1},\r\n x =\u003E 1.0,\r\n x =\u003E Math.Log(x));\r\n f(66.0); // 4.548\r\n\r\n\r\nLinearizing non-linear models by transformation\r\n-----------------------------------------------\r\n\r\nSometimes it is possible to transform a non-linear model into a linear one.\r\nFor example, the following power function\r\n\r\n$$$\r\nz : (x, y) \\mapsto u x^v y^w\r\n\r\ncan be transformed into the following linear model with $\\hat{z} = \\ln z$ and $t = \\ln u$\r\n\r\n$$$\r\n\\hat{z} : (x, y) \\mapsto t \u002B v \\ln x \u002B w \\ln y\r\n\r\n [lang=csharp]\r\n var xy = new[] {new[] { 1.0, 4.0 }, new[] { 2.0, 5.0 }, new[] { 3.0, 2.0 }};\r\n var z = new[] { 15.0, 20, 10 };\r\n\r\n var z_hat = z.Select(r =\u003E Math.Log(r)).ToArray(); // transform z_hat = ln(z)\r\n double[] p_hat = Fit.LinearMultiDim(xy, z_hat,\r\n d =\u003E 1.0,\r\n d =\u003E Math.Log(d[0]),\r\n d =\u003E Math.Log(d[1]));\r\n double u = Math.Exp(p_hat[0]); // transform t = ln(u)\r\n double v = p_hat[1];\r\n double w = p_hat[2];\r\n\r\n\r\nWeighted Regression\r\n-------------------\r\n\r\nSometimes the regression error can be reduced by dampening specific data points.\r\nWe can achieve this by introducing a weight matrix $W$ into the normal equations\r\n$\\mathbf{X}^T\\mathbf{y} = \\mathbf{X}^T\\mathbf{X}\\mathbf{p}$. Such weight matrices\r\nare often diagonal, with a separate weight for each data point on the diagonal.\r\n\r\n$$$\r\n\\mathbf{X}^T\\mathbf{W}\\mathbf{y} = \\mathbf{X}^T\\mathbf{W}\\mathbf{X}\\mathbf{p}\r\n\r\n [lang=csharp]\r\n var p = WeightedRegression.Weighted(X,y,W);\r\n\r\nWeighter regression becomes interesting if we can adapt them to the point of interest\r\nand e.g. dampen all data points far away. Unfortunately this way the model parameters\r\nare dependent on the point of interest $t$.\r\n\r\n [lang=csharp]\r\n // warning: preliminary api\r\n var p = WeightedRegression.Local(X,y,t,radius,kernel);\r\n\r\n\r\nRegularization\r\n--------------\r\n\r\n\r\nIterative Methods\r\n-----------------\r\n"},{"uri":"https://numerics.mathdotnet.com/ReleaseNotes-MKL.html","title":"MKL Provider Release Notes\r\n","content":"# MKL Provider Release Notes\r\n[Math.NET Numerics](ReleaseNotes.html) | [MKL Provider](ReleaseNotes-MKL.html) | [OpenBLAS Provider](ReleaseNotes-OpenBLAS.html)\r\n\r\n### 2.5.0 - 2021-01-01\r\n* r14 with Intel MKL 2020 Update 4\r\n* MKL Direct Sparse Solver provider *~Jong Hyun Kim*\r\n\r\n### 2.4.0 - 2020-05-22\r\n* r13 with Intel MKL 2020.0 Update 1\r\n\r\n### 2.3.0 - 2018-02-14\r\n* r12 with Intel MKL 2018.0 Update 1\r\n\r\n### 2.2.0 - 2016-10-30\r\n* r11 with Intel MKL 2017.0\r\n* Vector Functions v0.1: vector power\r\n* Fourier Transforms v1.0: basic FFT support\r\n\r\n### 2.1.0 - 2016-09-08\r\n* r10 with Intel MKL 2017.0\r\n\r\n### 2.0.0 - 2015-09-26\r\n* r9 with Intel MKL 11.3\r\n* Linear Algebra v2.0: automatic work array/buffer handling (breaking change)\r\n\r\n### 1.8.0 - 2015-05-09\r\n* r8 with Intel MKL 11.2 Update 3\r\n* New combined NuGet package including both 32 and 64 bit builds and a proper build target (Win only)\r\n\r\n### 1.7.0 - 2014-12-31\r\n* r7 with Intel MKL 11.2 Update 1\r\n* memory functions *~Marcus Cuda*\r\n\r\n### 1.6.0 - 2014-06-21\r\n* r6 with Intel MKL 11.1 Update 3\r\n* capability to control max number of threads\r\n\r\n### 1.5.0 - 2014-06-15\r\n* With Intel MKL 11.1 Update 3\r\n\r\n### 1.4.0 - 2014-03-01\r\n* With Intel MKL 11.1 Update 2\r\n* Capability querying support\r\n"},{"uri":"https://numerics.mathdotnet.com/ReleaseNotes-OpenBLAS.html","title":"OpenBLAS Provider Release Notes\r\n","content":"# OpenBLAS Provider Release Notes\r\n[Math.NET Numerics](ReleaseNotes.html) | [MKL Provider](ReleaseNotes-MKL.html) | [OpenBLAS Provider](ReleaseNotes-OpenBLAS.html)\r\n\r\n### 0.2.0 - 2015-09-26\r\n* Initial version\r\n"},{"uri":"https://numerics.mathdotnet.com/ReleaseNotes.html","title":"Math.NET Numerics Release Notes\r\n","content":"# Math.NET Numerics Release Notes\r\n[Math.NET Numerics](ReleaseNotes.html) | [MKL Provider](ReleaseNotes-MKL.html) | [OpenBLAS Provider](ReleaseNotes-OpenBLAS.html)\r\n\r\n### 5.0.0-alpha02 - 2021-07-11\r\n* COMPATIBILITY: net5.0, net48 better supported with explicit builds\r\n* COMPATIBILITY: netstandard1.x, net40, net45 no longer supported\r\n* BREAKING: drop all which was marked as obsolete\r\n* BREAKING: all native provider adapters moved out to separate NuGet packages\r\n* BREAKING: switch many usages of tuples to value tuples (experimental)\r\n* Distributions: Logistic *~Bobby Ingram*\r\n* Distributions: Perf: Cauchy avoid duplicate evaluation *~Febin*\r\n* Precision: Perf: pre-compute negative powers *~Febin*\r\n* Optimizations: Remove static properties in LevenbergMarquardtMinimizer *~Jong Hyun Kim*\r\n* Root Finding: Newton-Raphson better handling of zero-evaluations\r\n* Fit.Curve and FindMinimum extended to accept two more parameters\r\n* Series: stable series summation\r\n* Providers: drop managed reference linear algebra provider\r\n* Providers: native providers no longer inherit managed providers, managed now sealed\r\n* Providers: MKL provider compilation switched to Intel oneAPI MKL\r\n* Better support for System.Text.Json: Polynomial, DescriptiveStatistics *~Joseph Petersen*\r\n* Lots of internal cleanup, leveraging newer language features\r\n* Data: now released always together with Numerics (no longer separate versioning)\r\n* Control.Describe now includes CPU architecture and family identifier if know\r\n\r\n### 4.15.0 - 2021-01-07\r\n* Precision: Round (with integer part rounding) *~Jon Larborn*\r\n* Precision: RoundToMultiple, RoundToPower\r\n* F#: BigRational.FromDecimal *~Brian Berns*\r\n\r\n### 4.14.0 - 2021-01-01\r\n* Optimization: Avoid losing precision in golden section minimizer *~Daniel Fox*\r\n* Interpolation: Monotone-preserving Piecewise Cubic Hermite Polynomial (PCHIP) *~Febin*\r\n* Linear Algebra: Sparse COO format fix handling if not sorted or with duplicates *~Jong Hyun Kim*\r\n* Linear Algebra: Matrix.Resize\r\n\r\n### 4.13.0 - 2020-12-30\r\n* Linear Algebra: sparse solver native provider *~Jong Hyun Kim*\r\n* Polynomial: fix handling of zero polynomials *~Jakub Bialogrodzki*\r\n* AppSwitches support to disable native providers or their probing\r\n\r\n### 4.12.0 - 2020-08-92\r\n* Linear Algebra: allow zero-length vectors and matrices *~Evangelink*\r\n* Distributions: Beta-Binomial Distribution *~Andrew Willshire*\r\n* Special Functions: Generalized Hypergeometric, Rising and Falling Factorials *~Andrew Willshire*\r\n* Tests now work in more cultures *~Amaury Leve*\r\n* No more string resources\r\n* A couple immutable structs marked as readonly\r\n\r\n### 4.11.0 - 2020-05-24\r\n* Distributions: Skewed Generalized T and Error distributions *~Mikael Ohman*\r\n* BUG: Linear Algebra: fix Moore-Penrose Pseudo-Inverse for complex matrices *~Alex Hildebrand*\r\n* BUG: Linear Algebra: fix range in non-square diagonal sparse mixed products\r\n\r\n### 4.10.0 - 2020-05-24\r\n* Fractional Calculus: Riemann-Liouville fractional derivative *~Jong Hyun Kim*\r\n* Root Finding: accuracy range validation *~Ryan Grange*\r\n* Root Finding: behavior more consistent between native and managed provider\r\n\r\n### 4.9.1 - 2020-04-12\r\n* BUG: Optimization: weights were applied wrongly when evaluating the Jacobian *~Jong Hyun Kim, zhaochenxi*\r\n* BUG: Linear Algebra: F# Matrix.reduceRows was reducing columns instead of rows *~kayanme*\r\n* BUG: Distributions: Hypergeometric.CDF no longer returns values \u003E 1.0 *~Manor Askenazi*\r\n* Documentation: fix missing logarithms, drop old links *~Michel de Ruiter, Guney Ozsan*\r\n* Build: no longer code-sign the assemblies with a code-signing certificate, since it is too painful.\r\n\r\n### 4.9.0 - 2019-10-13\r\n* Integration: Substitution for open intervals *~Jong Hyun Kim*\r\n* Integration: Gauss-Kronrod Quadrature *~Jong Hyun Kim*\r\n* Integration: Complex contour *~Jong Hyun Kim*\r\n* Distributions: Three parameter Burr (Type XII) *~Philip Gruber*\r\n* Distributions: Inverse Gaussian *~Philip Gruber*\r\n* Distributions: Truncated Pareto *~Philip Gruber*\r\n* Optimization: Detect early completion in BFGS-B minimizer *~Tom McTiernan*\r\n\r\n### 4.8.1 - 2019-06-12\r\n* Packaging fix - signed edition was not properly strong named.\r\n\r\n### 4.8.0 - 2019-06-02\r\n* Optimization: Levenberg-Marquardt, Trust-Region Dogleg *~Jong Hyun Kim*\r\n* Optimization: Nelder-Mead-Simplex: Improve convergence for symmetrical functions *~Erik Ovegard*\r\n* BUG: Optimization: Nelder-Mead-Simplex did not return the best evaluated point in some cases *~Eric Scott Salem*\r\n* Factorial: first 170 values now constant (data segment) instead of precomputed on first use *~Portalez Regis*\r\n* Window Functions: Tukey window *~Marco Ross*\r\n\r\n### 4.7.0 - 2018-11-11\r\n* Special Functions: Airy functions Ai, Bi *~Jong Hyun Kim*\r\n* Special Functions: Bessel functions of the first and second kind *~Jong Hyun Kim*\r\n* Special Functions: Modified Bessel functions of the first and second kind *~Jong Hyun Kim*\r\n* Special Functions: Spherical Bessel functions of the first and second kind *~Jong Hyun Kim*\r\n* Special Functions: Hankel functions of the first and second kind *~Jong Hyun Kim*\r\n* Special Functions: Kelvin functions of the first and second kind, and derivatives *~Jong Hyun Kim*\r\n* Linear Algebra: optimized sparse implementation of transpose-multiply *~Richard Reader*\r\n* Linear Algebra: optimized range checking in vectors and matrices\r\n\r\n### 4.6.0 - 2018-10-19\r\n* Polynomial: New Polynomial data structure *~Tobias Glaubach*\r\n* Statistics: Correlate.Auto auto correlation *~Tobias Glaubach*\r\n* Curve Fitting: Fit.Curve for non-linear least-squares fitting to an arbitray function\r\n\r\n### 4.5.1 - 2018-05-22\r\n* Signed NuGet packages\r\n\r\n### 4.5.0 - 2018-05-22\r\n* Random: New Xoshiro256StarStar random source *~Colin Green*\r\n\r\n### 4.4.1 - 2018-05-06\r\n* Build: strong-name edition .Signed NuGet packages are available again\r\n\r\n### 4.4.0 - 2018-02-25\r\n* Linear Algebra: managed provider performance improvements on basic vector arithmetics\r\n\r\n### 4.3.0 - 2018-02-24\r\n* FFT: migrate managed algorithms to provider, streamline implementation wiring, scaling logic.\r\n* FFT: obsoleted algorithm-specific functions like Radix2Forward, they use Forward internally until v5.\r\n* FFT: migrate \u0022naive\u0022 implementation to tests as reference implementation.\r\n* Build: fix NuGet packaging sucht that the included assemblies are really code-signed.\r\n\r\n### 4.2.0 - 2018-02-21\r\n* Native Providers: MklProvider and similar types now public (entry point for memory management, etc)\r\n* Native Providers: All providers now support freeing resources without unloading the provider\r\n* Native Providers: MKL provider sets consistency, precision and accuracy modes earlier to ensure they are applied\r\n* Native Providers: If a provider has been loaded successfully, skip any future loading attempts (faster switching)\r\n* Build: add .Net Framework 4.6.1 target (main package), switch to 4.6.1 for testing projects\r\n\r\n### 4.1.0 - 2018-02-19\r\n* Curve Fitting: Fit.Power, Fit.Exponential, Fit.Logarithm (similar to excel trend curves)\r\n\r\n### 4.0.0 - 2018-02-11\r\n* Explicit builds for .Net Framework 4.0 and higher and for .Net Standard 1.3 and 2.0\r\n* F#: explicit builds for .Net Framework 4.5 and higher and for .Net Standard 1.6 and 2.0\r\n* BREAKING: drop obsolete functionality (which has been marked as obsolete for a while)\r\n* BREAKING: drop support for .Net 3.5 and PCL profiles\r\n* BREAKING: F#: drop support for .Net 4.0 and PCL profiles\r\n* BREAKING: F#: depends on FSharp.Core 4.3.3\r\n* BREAKING: Native provider implementation types internal (but can be constructed explicitly)\r\n* BREAKING: Native provider control API moved from Control to per-provider Control classes\r\n* BREAKING: Linear Algebra: Vector.Map consistent with Matrix.Map, automatic fallback to inplace\r\n* BREAKING: Linear Algebra: Storage providers must always force all parameters (no defaults)\r\n* BREAKING: Statistics: Ranks and RankInplace of single precision now return single precision arrays\r\n* BUG: Ode Solver: fix typo in the Runge-Kutta solvers on time-step handling *~Ksero*\r\n* BUG: fix Matrix.GetHashCode for wide matrices *~mjmckp*\r\n* BUG: Distributions: BetaScaled no longer ignores optional random source parameter\r\n* BUG: Trigonometry: Complex trigonometric functions behave better on large imput *~diluculo*\r\n* BUG: Trigonometry: Fix imaginary part sign of complex hyperbolic cotangent\r\n* Control.Describe: human readable summary of the effective Math.NET Numerics configuration\r\n* Providers: Native Provider support in .Net Standard 2.0 (but not in 1.x).\r\n* Linear Algebra: F# vector/matrix functions to accept all #seq instead of lists only\r\n* Linear Algebra: Vector MapInplace implemented at storage level\r\n* Curve Fitting: Fit.LineThroughOrigin shortcut\r\n* Optimization: Limited-Memory BFGS *~Florian Wechsung*\r\n* Root Finding: Broyden: step size for calculating appox Jacobian, more robust step size formula *~Aappo Pulkkinen*\r\n* Statistics: Kernel Density Estimation *~Christoph Albert*\r\n* Statistics: GoodnessOfFit CoefficientOfDetermination *~Jon Smit*\r\n* Fixed a whole range of inline documentation typos, misc code quality fixes *~Jonas Nyrup*\r\n* Examples: moved to examples folder, new framework target integration project file examples\r\n* Benchmarks: builds for both net46 and netcoreapp2.0\r\n* Assemblies are now code-signed with an X.509 certificate, using SHA2-256 hashes\r\n\r\n### 4.0.0-beta07 - 2018-02-10\r\n* Curve Fitting: Fit.LineThroughOrigin shortcut\r\n* Build: Target FSharp.Core 4.3.3 (for better netstandard2.0 compatibility)\r\n* Build: use latest SDKs and runtimes, cleanups\r\n\r\n### 4.0.0-beta06 - 2018-02-03\r\n* Rework conditional compilation to simplify and increase the .Net Standard api surface\r\n* BREAKING: Native provider implementation types internal (but can be constructed explicitly)\r\n* BREAKING: Native provider control API moved from Control to per-provider Control classes\r\n* Control.Describe: human readable summary of the effective Math.NET Numerics configuration\r\n* Fixed a whole range of inline documentation typos *~Jonas Nyrup*\r\n* Build: reworked test build targets, switched to Paket magic mode\r\n* Examples: moved to examples folder, new framework target integration project file examples\r\n\r\n### 4.0.0-beta05 - 2018-01-22\r\n* BUG: Distributions: BetaScaled no longer ignores optional random source parameter\r\n* BUG: Trigonometry: Complex trigonometric functions behave on large imput *~diluculo*\r\n* All: code quality fixes *~Jonas Nyrup*\r\n\r\n### 4.0.0-beta04 - 2018-01-13\r\n* BREAKING: Linear Algebra: Vector.Map consistent with Matrix.Map, automatic fallback to inplace\r\n* BREAKING: Linear Algebra: Storage providers must always force all parameters (no defaults)\r\n* Linear Algebra: F# vector/matrix functions to accept all #seq instead of lists only\r\n* Linear Algebra: Vector MapInplace implemented at storage level\r\n\r\n### 4.0.0-beta03 - 2018-01-09\r\n* Optimization: Limited-Memory BFGS *~Florian Wechsung*\r\n* BUG: Trigonometry: Fix imaginary part sign of complex hyperbolic cotangent\r\n\r\n### 4.0.0-beta02 - 2018-01-07\r\n* Root Finding: Broyden: step size for calculating appox Jacobian, more robust step size formula *~Aappo Pulkkinen*\r\n* Statistics: Kernel Density Estimation *~Christoph Albert*\r\n\r\n### 4.0.0-beta01 - 2018-01-07\r\n* BREAKING: drop obsolete functionality (which has been marked as obsolete for a while)\r\n* BREAKING: drop support for .Net 3.5 and PCL profiles\r\n* BREAKING: F#: drop support for .Net 4.0 and PCL profiles\r\n* BREAKING: F#: depends on FSharp.Core 4.2.3\r\n* Explicit builds for .Net Framework 4.0 and higher and for .Net Standard 1.3 and 2.0\r\n* F#: explicit builds for .Net Framework 4.5 and higher and for .Net Standard 1.6 and 2.0\r\n* Assemblies are now code-signed with an X.509 certificate, using SHA2-256 hashes\r\n* BUG: Ode Solver: fix typo in the Runge-Kutta solvers on time-step handling *~Ksero*\r\n* BUG: fix Matrix.GetHashCode for wide matrices *~mjmckp*\r\n\r\n### 3.20.2 - 2018-01-22\r\n* Bugfixes backported from v4:\r\n* BUG: Distributions: BetaScaled no longer ignores optional random source parameter\r\n* BUG: Trigonometry: Complex trigonometric functions behave on large imput *~diluculo*\r\n\r\n### 3.20.1 - 2018-01-13\r\n* Bugfixes backported from v4:\r\n* BUG: Trigonometry: Fix imaginary part sign of complex hyperbolic cotangent\r\n* BUG: Ode Solver: fix typo in the Runge-Kutta solvers on time-step handling *~Ksero*\r\n* BUG: fix Matrix.GetHashCode for wide matrices *~mjmckp*\r\n\r\n### 3.20.0 - 2017-07-15\r\n* Optimization: non-linear optimization algorithms *~Scott Stephens, Erik Ovegard, bdodson, et al.*\r\n* Native Providers: from now on also supported in the .Net 3.5 build.\r\n* BUG: Special Functions: allow more iterations in BetaRegularized *~Elias Abou Jaoude*\r\n\r\n### 3.19.0 - 2017-04-29\r\n* Statistics: RunningStatistics.Combine to better handle empty statistics *~Lucas Godshalk*\r\n* Linear Algebra: Cholesky.Factorize to reuse the factorization matrix *~mjmckp*\r\n* Linear Algebra: Fix docs for DoPointwiseMultiply *~Jakub Arnold*\r\n\r\n### 3.18.0 - 2017-04-09\r\n* FFT: single-precision support *~AlexHild*\r\n\r\n### 3.17.0 - 2017-01-15\r\n* Random: random sources (all except crypto) now support ephemeral serialization.\r\n* Linear Algebra: explicit impl to copy a range of a row of a sparse matrix to a range of a sparse vector *~arthurvb*\r\n* Linear Algebra: explicitly demand fully modifiable matrix where needed, fixes issues with diagonal matrices.\r\n* FFT: leverage new matrix internal array access approach in 2D matrix transformations.\r\n\r\n### 3.16.0 - 2017-01-03\r\n* Root Finding: improve accuracy handling *~Konstantin Tretyakov*\r\n* Regression: GoodnessOfFit StandardError *~David Falkner*\r\n\r\n### 3.15.0 - 2016-12-27\r\n* FFT: MKL native provider backend.\r\n* FFT: 2D and multi-dimensional FFT (only supported by MKL provider, managed provider pending).\r\n* FFT: real conjugate-even FFT (only leveraging symmetry in MKL provider).\r\n* FFT: managed provider significantly faster on x64.\r\n* Linear Algebra: pointwise trigonometric and basic functions *~Albert Pang*\r\n* Linear Algebra: better support for F# built-in operators (sqrt, sin, exp, ..) *~Albert Pang*\r\n* Linear Algebra: pointwise power operator (F#)\r\n* Linear Algebra: enable experimental matrix product implementation\r\n* Linear Algebra: better support for matrix to/from row-major arrays and enumerables\r\n* Linear Algebra: transport allows specifying a result matrix to transpose into, inplace if square\r\n* Linear Algebra: vector and matrix AsArray and similar to access internal arrays if applicable\r\n* Linear Algebra: vector and matrix pointwise min/max and absmin/absmax\r\n* Linear Algebra: dot-power on vectors and matrices, supporting native providers.\r\n* Linear Algebra: matrix Moore-Penrose pseudo-inverse (SVD backed).\r\n* Provider Control: separate Control classes for LA and FFT Providers.\r\n* Provider Control: avoid internal exceptions on provider discovery.\r\n* Distributions: fix misleading inline docs on Negative-Binomial.\r\n* Generate: linear integer ranges\r\n* Root Finding: extend zero-crossing bracketing in derivative-free algorithms.\r\n* Window: periodic versions of Hamming, Hann, Cosine and Lanczos windows.\r\n* Special Functions: more robust GammaLowerRegularizedInv (and Gamma.InvCDF).\r\n* BUG: ODE Solver: fix bug in Runge-Kutta second order routine *~Ksero*\r\n\r\n### 3.13.1 - 2016-09-06\r\n* BUG: Random: Next(x,x\u002B1) must always return x *~Juri*\r\n\r\n### 3.13.0 - 2016-08-18\r\n* Linear Algebra: faster tall, wide managed matrix multiplication. *~Aixile*\r\n* Euclid: Integer Log2 (DeBruijn sequencences algorithm).\r\n* Integration: Gauss-Legendre documentation, cleanup. *~Larz White*\r\n* Random: Integer sub-range sampling to use rejection sampling to avoid bias.\r\n* Random: Improvements on integer and byte sampling.\r\n* BUG: Random: CryptoRandomSource must not generate 1.0 samples.\r\n* BUG: Statistics: fixed bug in WeightedPearson Correlation. *~Jon Smit*\r\n\r\n### 3.12.0 - 2016-07-03\r\n* ODE Solver: Runge-Kutta (order 2, 4) and Adams-Bashforth (order 1-4) algorithms *~Yoonku Hwang*\r\n* Linear Algebra: faster multiplication of sparse with dense matrices *~Arthur*\r\n* BUG: Integration: Gauss-Legendre on order 256 *~Sergey Kosukhin*\r\n* BUG: Distributions: ChiSquared sampling was taking a square root where it should not *~Florian Wechsung*\r\n\r\n### 3.11.1 - 2016-04-24\r\n* BUG: Linear Algebra: sparse vector pointwise multiply/divide to itself\r\n* BUG: Linear Algebra: Vector.ToVectorString if the first column is wider than maxWidth\r\n\r\n### 3.11.0 - 2016-02-13\r\n* Special Functions: error functions to use static coefficient arrays (perf) *~Joel Sleppy*\r\n* Integration: Gauss-Legendre Rule (1D, 2D) *~Larz White*\r\n* Complex: more robust magnitude and division for numbers close to MaxValue or Epsilon *~MaLiN2223*\r\n* Native Providers: lazy default provider discovery \u0026 initialization *~Kuan Bartel*\r\n* FSharp Package: Quaternion type *~Phil Cleveland*\r\n\r\n### 3.10.0 - 2015-12-30\r\n* Statistics: single-precision floating point support.\r\n* Statistics: very limited support for int32 and complex numbers.\r\n* Statistics: Min/Max Absolute, MagnitudePhase (complex).\r\n* Statistics: FiveNumberSummary to use actual Median instead of R8 quantile.\r\n* Linear Algebra: matrix Rank to use relative epsilon.\r\n* Linear Algebra: extensions to convert between single/double precision, complex/real.\r\n* Linear Algebra: Vector/Matrix storage DataContracts for ephemeral serialization.\r\n* Regression: more helpful exceptions and messages.\r\n* Random: \u0027Next\u0027 integer sampling no longer involves floating points, avoids one-off error in MersenneTwister.\r\n* Precision: EpsilonOf for single-precision numbers, drop no longer needed portable fallbacks.\r\n\r\n### 3.9.0 - 2015-11-25\r\n* Distributions: Normal.CDF avoids problematic subtraction by using Erfc instead of Erf.\r\n* Statistics: geometric and harmonic mean.\r\n* Statistics: DataContracts for ephemeral serialization on RunningStatistics, DescriptiveStatistics and Histogram.\r\n* BUG: Statistics: Histogram did not adjust lower bound correctly when value was equal to the bound *~Volker Breuer*\r\n* Linear Algebra: minor optimization on how we call Array.Copy.\r\n* BUG: Linear Algebra: fix bug in Complex and Complex32 SparseMatrix.ToTypeString.\r\n\r\n### 3.8.0 - 2015-09-26\r\n* Distributions: PDF and CDF more robust for large distribution parameters.\r\n* Distributions: BetaScaled distribution.\r\n* Distributions: method to create a PERT distribution (based on BetaScaled) *~John C Barstow*\r\n* Distributions: Weibull.Estimate *~Jon Larborn*\r\n* Random: NextBoolean extensions.\r\n* Root Finding: RootFinding.Secant (based on NewtonRaphson) *~grovesNL*\r\n* Linear Algebra: Matrix Rank calculation now uses a tolerance based on the matrix size.\r\n* Linear Algebra: Alternative CreateMatrix/Vector functions with type parameter on functions instead of type.\r\n* Linear Algebra: MKL LinearAlgebra provider requires at least native provider r9 (linear algebra v2.0).\r\n* Native Providers: automatic handling of intermediate work arrays/buffers in MKL and OpenBLAS providers *~Marcus Cuda, Kuan Bartel*\r\n* Native Providers: automatically use native provider if available.\r\n* Native Providers: new Control.TryUse* to make it simpler to use providers if available but without failing if not.\r\n* Native Providers: improved error state checking and handling *~Marcus Cuda, Kuan Bartel*\r\n* Combinatorics: generate or select random permutation, combination or variation (shuffling)\r\n* Finance: rename CompoundMonthlyReturn to CompoundReturn (old now obsolete).\r\n\r\n### 3.7.1 - 2015-09-10\r\n* BUG: Linear Algebra: fix optimized path of adding a sparse matrix to itself.\r\n\r\n### 3.7.0 - 2015-05-09\r\n* Statistics: RunningStatistics now propagates min/max on Combine, handles NaN on Push.\r\n* Statistics: new MovingStatistics providing descriptive statistics over a moving window *~Marcus Cuda*\r\n* Statistics: new Statistics.MovingAverage.\r\n* Statistics: Improved Histogram handling of small-width buckets *~Justin Needham*\r\n* Distributions: ChiSquare.InvCDF *~logophobia*\r\n* FFT: Fourier.FrequencyScale to generate the frequency corresponding to each index in frequency space.\r\n* BUG: FFT: fix Bluestein algorithm for sequences with more than 46341 samples but not power-of-two.\r\n* Linear Algebra: SparseVector.AbsoluteMaximumIndex *~Matt Heffron*\r\n* MKL Native Provider: OSX build script *~Marcus Cuda*\r\n* MKL Native Provider: new combined NuGet package with a proper build target (no more manual file handling needed).\r\n* OpenBLAS Native Provider: a new linear algebra provider using OpenBLAS *~Kuan Bartel*\r\n* CUDA Native Provider: a new GPU-based linear algebra provider using Nvidia CUDA *~Matthew A. Johnson*\r\n* Native Providers: now versioned separately for each kind (MKL, CUDA, OpenBLAS).\r\n\r\n### 3.6.0 - 2015-03-22\r\n* Distributions: ChiSquare.CDF more robust for large numbers *~Baltazar Bieniek*\r\n* Linear Algebra: MatrixStorage.Map2 equivalent to VectorStorage.Map2\r\n* Linear Algebra: Matrix and Vector Find/Find2, Exists/Exists2, ForAll/ForAll2\r\n* Linear Algebra: more consistent range checking in MatrixStorage.Clear and related\r\n* Linear Algebra: mixed-storage fall back implementations now leverage higher-order functions\r\n* BUG: Linear Algebra: fix loop range in MatrixStorage.ClearColumns (built-in storage not affected)\r\n* BUG: Linear Algebra: fix sparse matrix equality.\r\n* BUG: Linear Algebra: ArgumentException instead of index exception when trying to create an empty matrix.\r\n* Generate: Unfold, Fibonacci; Normal and Standard replacing Gaussian and Stable.\r\n* Native Providers: NativeProviderLoader to automatically load the provider for the matching processor architecture (x86, x64) *~Kuan Bartel*\r\n* Native Providers: Control.NativeProviderPath allowing to explicitly declare where to load binaries from.\r\n* MKL Native Provider: support for native complex eigen-value decomposition *~Marcus Cuda*\r\n* MKL Native Provider: non-convergence checks in singular-value and eigen-value decompositions *~Marcus Cuda*\r\n\r\n### 3.5.0 - 2015-01-10\r\n* Differentiation: derivative, partial and mixed partial; hessian \u0026 jacobian *~Hythem Sidky*\r\n* Differentiation: Differentiate facade class for simple use cases\r\n* Differentiation: F# module for better F# function support.\r\n* Linear Algebra: matrix ToRowArrays/ToColumnArrays\r\n* Linear Algebra: F# insertRow, appendRow, prependRow and same also for columns\r\n* Linear Algebra: F# append, stack and ofMatrixList2\r\n* Precision: measured machine epsilon, positive vs negative epsilon\r\n\r\n### 3.4.0 - 2015-01-04\r\n* Special Functions: Generalized Exponential Integral *~Ashley Messer*\r\n* Special Functions: Regularized Incomplete Gamma domain extended to a=0 *~Ashley Messer*\r\n* Statistics: weighted Pearson correlation *~ViK*\r\n* MKL Native Provider: memory functions to free buffers and gather usage statistics *~Marcus Cuda*\r\n* F#: depend on new official FSharp.Core NuGet package instead of FSharp.Core.Microsoft.Signed\r\n* F#: simpler NuGet package dependencies (no more need for framework groups)\r\n* Build: vagrant bootstrap now uses the latest xamarin mono packages\r\n\r\n### 3.3.0 - 2014-11-26\r\n* Linear Algebra: Vector.Fold2 (fold2 in F#), storage optimized\r\n* Linear Algebra: Minor change how matrix products call the LA provider\r\n* Linear Algebra: Random generation now leveraging array sampling routines\r\n* BUG: Linear Algebra: fix bug when manually assigning System.Random to random distribution\r\n* Root Finding: Change Brent tolerance check, add bracket check *~Hythen Sidky*\r\n* Root Finding: Auto zero-crossing bracketing in FindRoots facade (not in algorithms)\r\n* Statistics: RootMeanSquare (RMS)\r\n* Distributions: Array sampling routines now available through interface\r\n* Distributions: Categorical sampling now explicitly skips p=0 categories\r\n* Generate: leverage array sampling routines for random data generation\r\n* Generate: square, triangle and sawtooth waves\r\n* Distance: Jaccard Index\r\n* F#: explicitly depend on official FSharp.Core NuGet packages\r\n* F#: NuGet package with iPython IfSharp F# module integration load script\r\n* F#: load scripts with better packet support (and NuGet with -ExcludeVersion)\r\n* Build: unified build.sh and buildn.sh into combined build.sh\r\n* Build: use Paket instead of NuGet to maintain NuGet dependencies\r\n* Build: for core add PCL profiles 7, 78 and 259; for F# extensions drop PCL profile 328\r\n\r\n### 3.2.3 - 2014-09-06\r\n* BUG: MatrixNormal distribution: fix density for non-square matrices *~Evelina Gabasova*\r\n\r\n### 3.2.2 - 2014-09-05\r\n* BUG: MatrixNormal distribution: density computation switched row and column covariance *~Evelina Gabasova*\r\n\r\n### 3.2.1 - 2014-08-05\r\n* Package fix: make sure .Net 3.5-only dependencies are not installed on .Net 4 and newer.\r\n\r\n### 3.2.0 - 2014-08-05\r\n* Linear Algebra: Vector.Map2 (map2 in F#), storage-optimized\r\n* Linear Algebra: fix RemoveColumn/Row early index bound check (was not strict enough)\r\n* Statistics: Entropy *~Jeff Mastry*\r\n* Interpolation: use Array.BinarySearch instead of local implementation *~Candy Chiu*\r\n* Resources: fix a corrupted exception message string\r\n* Portable Build: support .Net 4.0 as well by using profile 328 instead of 344.\r\n* .Net 3.5: F# extensions now support .Net 3.5 as well\r\n* .Net 3.5: NuGet package now contains proper 3.5-only TPL package dependency; also in Zip package\r\n\r\n### 3.1.0 - 2014-07-20\r\n* Random: generate a sequence of integers within a range in one go\r\n* Distributions: all distributions must have static routines to sample an array in one go\r\n* Linear Algebra: fix Matrix.StrictlyLowerTriangle\r\n* Linear Algebra: fix vector DoOuterProduct *~mjmckp*\r\n* Linear Algebra: enumerators accept Zeros-parameter (like map/fold already does)\r\n* Linear Algebra: Vector.MapConvert (consistency)\r\n* Linear Algebra: proper term for \u0027conjugate symmetric\u0027 is \u0027Hermitian\u0027\r\n* Interpolation: new Step, LogLinear and transformed interpolators *~Candy Chiu*\r\n* Interpolation: check for min required number of data points, throw ArgumentException if not.\r\n* Root Finding: F# FindRoots.broyden module function *~teramonagi*\r\n* Misc docs fixes\r\n\r\n### 3.0.2 - 2014-06-26\r\n* BUG: fixing a bug in Matrix.RemoveRow range checks.\r\n\r\n### 3.0.1 - 2014-06-24\r\n* BUG: fixing a bug in new Matrix.ToMatrixString and Vector.ToVectorString routines.\r\n\r\n### 3.0.0 - 2014-06-21\r\n* First stable v3 release:\r\n * [Upgrade Notes](https://github.com/mathnet/mathnet-numerics/wiki/Upgrading-to-Version-3)\r\n * Stable API, no more breaking changes for all future v3 releases (except previews).\r\n * Finally unlocks development and contributions around non-linear optimization and native providers over the next few minor releases.\r\n* Native Providers: option to control max number of threads used by MKL.\r\n* F#: Fit.multiDim; Matrix.qr, svd, eigen, lu and cholesky.\r\n\r\n### 3.0.0-beta05 - 2014-06-20\r\n* 2nd Candidate for v3.0 Release\r\n* BUG: Distance: fix bug in Hamming distance that skipped the first pair.\r\n* F#: packages now include a MathNet.Numerics.fsx script that includes FSI printers and references the assemblies.\r\n* Linear Algebra: improved matrix and vector ToString formatting, more compact, adaptive to actual numbers.\r\n* Linear Algebra: CoerceZero for matrix and vector to replace small numbers with zero.\r\n* Regression: DirectRegressionMethod option to specify as argument which direct method should be used.\r\n* Control: drop MaxToStringRows/Columns properties (no longer used)\r\n* Random: clarify bad randomness properties of SystemRandomSource.FastDoubles (trade off)\r\n\r\n### 3.0.0-beta04 - 2014-06-16\r\n* Candidate for v3.0 Release\r\n* Linear Algebra:\r\n * FoldRows renamed to FoldByRow, now operates on and returns arrays; same for columns. **Breaking.**\r\n * New FoldRows and ReduceRows that operate on row vectors; same for columns\r\n * Split Map into Map and MapConvert (allows optimization in common in-place case)\r\n * Row and column sums and absolute-sums\r\n * F# DiagonalMatrix module to create diagonal matrices without using the builder\r\n * F# Matrix module extended with sumRows, sumAbsRows, normRows; same for columns\r\n* Build: extend build and release automation, automatic releases also for data extensions and native providers\r\n\r\n### 3.0.0-beta03 - 2014-06-05\r\n* Linear Algebra: vector outer product now follows common style, supports explicit result argument, more efficient.\r\n* Interpolation: must not modify/sort original data; alternative Sorted and Inplace functions.\r\n* Distributions: static IsValidParameterSet functions.\r\n* Distributions: all distributions are now immutable in their distribution parameters. **Breaking.**\r\n* NuGet: attempt to create proper symbol\u002Bsource packages on symbolsource; primary packages smaller, w/o pdbs\r\n* Build: skip long tests with new \u0022quick\u0022 argument (FAKE)\r\n* Build: clearing is more explicit, fixes most locking issues if solution is also open in IDE.\r\n* Build: automated publishing docs, api, git release tag (maintainer)\r\n\r\n### 3.0.0-beta02 - 2014-05-29\r\n* Linear Algebra:\r\n * optimized sparse-sparse and sparse-diagonal matrix products. *~Christian Woltering*\r\n * transpose at storage level, optimized sparse transpose. *~Christian Woltering*\r\n * optimized inplace-map, indexed submatrix-map.\r\n * optimized clearing a set of rows or columns.\r\n * matrix FoldRows/FoldColumns.\r\n * matrix column/row norms, normalization.\r\n * prefer enums over boolean parameters (e.g. \u0060Zeros.AllowSkip\u0060).\r\n * IsSymmetric is now a method, add IsConjugateSymmetric. **Breaking.**\r\n * Eigenvalue decomposition can optionally skip symmetry test.\r\n * Direct diagonal-scalar division implementation\r\n* Test Functions: Rosenbrock, Rastrigin, DropWave, Ackley, Bohachevsky, Matyas, SixHumpCamel, Himmelblau\r\n* Statistics: DescriptiveStatistics support for larger datasets.\r\n* MKL: native providers must not require MFC to compile.\r\n* Sorting helpers support sub-range sorting, use insertion sort on very small sets.\r\n* Build: extend usage of FAKE, automate docs, api, Zip and NuGet package generation.\r\n* Portable: replace PCL profile 136 with profile 344, support for WP8.1\r\n* Xamarin: prepare for better Xamarin Android/iOS support and for adding to the Xamarin store (free).\r\n* Misc code style fixes.\r\n* Update Vagrant setup to official Ubuntu 14.04 LTS box and proper apt-style Mono\u002BF# provisioning.\r\n\r\n### 3.0.0-beta01 - 2014-04-01\r\n* See also: [Roadmap](https://sdrv.ms/17wPFlW) and [Towards Math.NET Numerics Version 3](https://christoph.ruegg.name/blog/towards-mathnet-numerics-v3.html).\r\n* **Major release with breaking changes**\r\n* All obsolete code has been removed\r\n* Reworked redundancies, inconsistencies and unfortunate past design choices.\r\n* Significant namespace simplifications (-30%).\r\n* Linear Algebra:\r\n * Favor and optimize for generic types, e.g. \u0060Vector\u003Cdouble\u003E\u0060.\r\n * Drop the \u0060.Generic\u0060 in the namespaces and flattened solver namespaces.\r\n * F#: all functions in the modules now fully generic, including the \u0060matrix\u0060 function.\r\n * F#: \u0060SkipZeros\u0060 instead of the cryptic \u0060nz\u0060 suffix for clarity.\r\n * Add missing scalar-matrix routines.\r\n * Optimized mixed dense-diagonal and diagonal-dense operations (500x faster on 250k set).\r\n * More reasonable choice of return structure on mixed operations (e.g. dense\u002Bdiagonal).\r\n * Add point-wise infix operators \u0060.*\u0060, \u0060./\u0060, \u0060.%\u0060 where supported (F#)\r\n * Vectors explicitly provide proper L1, L2 and L-infinity norms.\r\n * All norms return the result as double (instead of the specific value type of the matrix/vector).\r\n * Matrix L-infinity norm now cache-optimized (8-10x faster).\r\n * Vectors have a \u0060ConjugateDotProduct\u0060 in addition to \u0060DotProduct\u0060.\r\n * \u0060Matrix.ConjugateTransposeAndMultiply\u0060 and variants.\r\n * Matrix Factorization types fully generic, easily accessed by new \u0060Matrix\u003CT\u003E\u0060 member methods (replacing the extension methods). Discrete implementations no longer visible.\r\n * QR factorization is thin by default.\r\n * Matrix factorizations no longer clone their results at point of access.\r\n * Add direct factorization-based \u0060Solve\u0060 methods to matrix type.\r\n * Massive iterative solver implementation/design simplification, now mostly generic and a bit more functional-style.\r\n * Renamed iterative solver stop criteria from \u0027criterium\u0027 to \u0027criterion\u0027.\r\n * New MILU(0) iterative solver preconditioner that is much more efficient and fully leverages sparse data. *~Christian Woltering*\r\n * Matrices/Vectors now have more consistent enumerators, with a variant that skips zeros (useful if sparse).\r\n * Matrix/Vector creation routines have been simplified and usually no longer require explicit dimensions. New variants to create diagonal matrices, or such where all fields have the same value. All functions that take a params array now have an overload accepting an enumerable (e.g. \u0060OfColumnVectors\u0060).\r\n * Generic Matrix/Vector creation using builders, e.g. \u0060Matrix\u003Cdouble\u003E.Build.DenseOfEnumerable(...)\u0060\r\n * Create a matrix from a 2D-array of matrices (top-left aligned within the grid).\r\n * Create a matrix or vector with the same structural type as an example (\u0060.Build.SameAs(...)\u0060)\r\n * Removed non-static Matrix/Vector.CreateMatrix/CreateVector routines (no longer needed)\r\n * Add Vector.OfArray (copying the array, consistent with Matrix.OfArray - you can still use the dense vector constructor if you want to use the array directly without copying).\r\n * More convenient and one more powerful overload of \u0060Matrix.SetSubMatrix\u0060.\r\n * Matrices/Vectors expose whether storage is dense with a new IsDense property.\r\n * Various minor performance work.\r\n * Matrix.ClearSubMatrix no longer throws on 0 or negative col/row count (nop)\r\n * BUG: Fix bug in routine to copy a vector into a sub-row of a matrix.\r\n * Both canonical modulus and remainder operations on matrices and vectors.\r\n * Matrix kernel (null space) and range (column space)\r\n * Storage-aware non-inplace functional map on vectors and matrices\r\n * Pointwise power, exponential and natural logarithm for vectors and matrices.\r\n * Matrix positive-integer power\r\n * Matrix RemoveRow/RemoveColumn; more efficient InsertRow/InsertColumn\r\n* Native Linear Algebra/Intel MKL:\r\n * Thin QR factorization uses MKL if enabled for all types (previously just \u0060double\u0060)\r\n * Sparse matrix CSR storage format now uses the much more common row pointer convention and is fully compatible with MKL (so there is nothing in the way to add native provider support).\r\n * Providers have been moved to a \u0060Providers\u0060 namespace and are fully generic again.\r\n * Simpler provider usage: \u0060Control.UseNativeMKL()\u0060, \u0060Control.UseManaged()\u0060.\r\n * MKL native provider now supports capability querying (so we can extend it much more reliably without breaking your code).\r\n * MKL native provider consistency, precision and accuracy now configurable (trade-off).\r\n * Native Provider development has been reintegrated into the main repository; we can now directly run all unit tests against local native provider builds. Covered by FAKE builds.\r\n* Statistics:\r\n * Pearson and Spearman correlation matrix of a set of arrays.\r\n * Spearman ranked correlation optimized (4x faster on 100k set)\r\n * Skewness and PopulationSkewness; Kurtosis and PopulationKurtosis.\r\n * Single-pass \u0060MeanVariance\u0060 and \u0060MeanStandardDeviation\u0060 methods (often used together).\r\n * Some overloads for single-precision values.\r\n * Add \u0060Ranks\u0060, \u0060QuantileRank\u0060 and \u0060EmpiricalCDF\u0060.\r\n * F# module for higher order functions.\r\n * Median direct implementation (instead of R8-compatible 0.5-quantile)\r\n * New RunningStatistics that can be updated and merged\r\n * BUG: DescriptiveStatistics must return NaN if not enough data for a specific statistic.\r\n* Probability Distributions:\r\n * Direct static distributions functions (PDF, CDF, sometimes also InvCDF).\r\n * Direct static sample functions, including such to fill an existing array in one call.\r\n * New Trigangular distribution *~Superbest, David Prince*\r\n * Add InvCDF to Gamma, Student-T, FisherSnedecor (F), and Beta distributions.\r\n * Major API cleanup, including xml docs\r\n * Xml doc and ToString now use well-known symbols for the parameters.\r\n * Maximum-likelihood parameter estimation for a couple distributions.\r\n * All constructors now optionally accept a random source as last argument.\r\n * Use less problematic RNG-seeds by default, if no random source is provided.\r\n * Simpler and more composable random sampling from distributions.\r\n * Much more distribution\u0027s actual sample distribution is verified in tests (all continuous, most discrete).\r\n * Binomial.CDF now properly leverages BetaRegularized.\r\n * BUG: Fix hyper-geometric CDF semantics, clarify distribution parameters.\r\n * BUG: Fix Zipf CDF at x=1.\r\n * BUG: Fix Geometric distribution sampling.\r\n * BUG: Fix Categorical distribution properties. *~David Prince*\r\n* Random Numbers:\r\n * All RNGs provide static Sample(values) functions to fill an existing array.\r\n * Thread-safe System.Random available again as \u0060SystemRandomSource\u0060.\r\n * Fast and simple to use static \u0060SystemRandomSource.Doubles\u0060 routine with lower randomness guarantees.\r\n * Shared \u0060SystemRandomSource.Default\u0060 and \u0060MersenneTwister.Default\u0060 instances to skip expensive initialization.\r\n * Using thread-safe random source by default in distributions, Generate, linear algebra etc.\r\n * Tests always use seeded RNGs for reproducability.\r\n * F#: direct sampling routines in the \u0060Random\u0060 module, also including default and shared instances.\r\n* Linear Regression:\r\n * Reworked \u0060Fit\u0060 class, supporting more simple scenarios.\r\n * New \u0060.LinearRegression\u0060 namespace with more options.\r\n * Better support for simple regression in multiple dimensions.\r\n * Goodness of Fit: R, RSquared *~Ethar Alali*\r\n * Weighted polynomial and multi-dim fitting.\r\n * Use more efficient LA routines *~Thomas Ibel*\r\n* Interpolation:\r\n * Return tuples instead of out parameter.\r\n * Reworked splines, drop complicated and limiting inheritance design. More functional approach.\r\n * More efficient implementation for non-cubic splines (especially linear spline).\r\n * \u0060Differentiate2\u0060 instead of \u0060DifferentiateAll\u0060.\r\n * Definite \u0060Integrate(a,b)\u0060 in addition to existing indefinite \u0060Integrate(t)\u0060.\r\n * Use more common names in \u0060Interpolate\u0060 facade, e.g. \u0022Spline\u0022 is a well known name.\r\n* Root Finding: Chebychev polynomial roots.\r\n* Root Finding: Cubic polynomials roots. *~Candy Chiu*\r\n* Trig functions: common short names instead of very long names. Add sinc function.\r\n* Excel functions: TDIST, TINV, BETADIST, BETAINV, GAMMADIST, GAMMAINV, NORMDIST, NORMINV, NORMSDIST, NORMSINV QUARTILE, PERCENTILE, PERCENTRANK.\r\n* Special functions: BetaRegularized more robust for large arguments.\r\n* Special functions: new \u0060GammaLowerRegularizedInv\u0060.\r\n* New distance functions in \u0060Distance\u0060: euclidean, manhattan, chebychev distance of arrays or generic vectors. SAD, MAE, SSD, MSE metrics. Pearson\u0027s, Canberra and Minkowski distance. Hamming distance.\r\n* Windows: ported windowing functions from Neodym (Hamming, Hann, Cosine, Lanczos, Gauss, Blackmann, Bartlett, ...)\r\n* BigInteger factorial\r\n* Build:\r\n * FAKE-based build (in addition to existing Visual Studio solutions) to clean, build, test, document and package independently of the CI server.\r\n * Finally proper documentation using FSharp.Formatting with sources included in the repository so it is versioned and can be contributed to with pull requests.\r\n * NuGet packages now also include the PCL portable profile 47 (.Net 4.5, Silverlight 5, Windows 8) in addition to the normal .Net 4.0 build and PCL profile 136 (.Net 4.0, WindowsPhone 8, Silverlight 5, Windows 8) as before. Profile 47 uses \u0060System.Numerics\u0060 for complex numbers, among others, which is not available in profile 136.\r\n * NuGet packages now also include a .Net 3.5 build of the core library.\r\n * IO libraries have been removed, replaced with new \u0060.Data\u0060 packages (see list on top).\r\n * Alternative strong-named versions of more NuGet packages (mostly the F# extensions for now), with the \u0060.Signed\u0060 suffix.\r\n * Reworked solution structure so it works in both Visual Studio 11 (2012) and 12 (2013).\r\n * We can now run the full unit test suite against the portable builds as well.\r\n * Builds should now also work properly on recent Mono on Linux (including F# projects).\r\n * Fixed builds on platforms with case sensitive file systems. *~Gauthier Segay*\r\n* Integration: simplification of the double-exponential transformation api design.\r\n* FFT: converted to static class design and shorter names for simpler usage. Drop now redundant \u0060Transform\u0060 class.\r\n* Generate: ported synthetic data generation and sampling routines from Neodym (includes all from old Signals namespace). F# module for higher order functions.\r\n* Euclid: modulus vs remainder (also BigInteger), integer theory (includes all from old NumberTheory namespace).\r\n* Complex: common short names for Exp, Ln, Log10, Log.\r\n* Complex: fix issue where a *negative zero* may flip the sign in special cases (like \u0060Atanh(2)\u0060, where incidentally MATLAB and Mathematica do not agree on the sign either).\r\n* Complex: routines to return all two square and three cubic roots of a complex number.\r\n* Complex: More robust complex Asin/Acos for large real numbers.\r\n* Evaluate: routine to evaluate complex polynomials, or real polynomials at a complex point.\r\n* CommonParallel now also supported in .Net 3.5 and portable profiles; TaskScheduler can be replaced with custom implementation *~Thomas Ibel*\r\n* F# BigRational type cleaned up and optimized *~Jack Pappas*\r\n* F# BigRational IsZero, IsOne, IsInteger, create from fraction.\r\n* F# BigRational Reciprocal, Power operator support (**), support for negative integer powers.\r\n* F# functions now use the clearer \u0060Func\u0060 suffix instead of just \u0060F\u0060 if they return a function.\r\n* Precision: reworked, now much more consistent. **If you use \u0060AlmostEqual\u0060 with numbers-between/ULP semantics, please do review your code to make sure you\u0027re still using the expected variant!**. If you use the decimal-places semantics, you may need to decrement the digits argument to get the same behavior as before.\r\n* Much less null checks, our code generally only throws \u0060ArgumentNullException\u0060 if an unexpected null argument would *not* have caused an immediate \u0060NullReferenceException\u0060.\r\n* Cases where \u0060ArgumentOutOfRangeExceptions\u0060 where thrown with wrong arguments (i.e. no parameter name) now throw \u0060ArgumentException\u0060 instead.\r\n* Tests now have category attributes (to selectively run or skip categories).\r\n\r\n### 2.6.2 - 2013-10-21\r\n* Patch release, fixing the NuGet package to work better in WindowsPhone 8 projects. Assemblies are not changed.\r\n\r\n### 2.6.1 - 2013-08-13\r\n* BUG: fixing a bug in \u0060ArrayStatistics.Variance\u0060 on arrays longer than 46341 entries.\r\n\r\n### 2.6.0 - 2013-07-26\r\n* See also: [What\u0027s New in Math.NET Numerics 2.6](https://christoph.ruegg.name/blog/new-in-mathnet-numerics-2-6.html)\r\n* Linear Curve Fitting: Linear least-squares fitting (regression) to lines, polynomials and linear combinations of arbitrary functions. Multi-dimensional fitting. Also works well in F# with the F# extensions.\r\n* Root Finding:\r\n * Brent\u0027s method. *~Candy Chiu, Alexander T\u00E4schner*\r\n * Bisection method. *~Scott Stephens, Alexander T\u00E4schner*\r\n * Broyden\u0027s method, for multi-dimensional functions. *~Alexander T\u00E4schner*\r\n * Newton-Raphson method.\r\n * Robust Newton-Raphson variant that tries to recover automatically in cases where it would fail or converge too slowly. This modification makes it more robust e.g. in the presence of singularities and less sensitive to the search range/interval.\r\n * All algorithms support a TryFind-pattern which returns success instead of throwing an exception.\r\n * Special case for quadratic functions, in the future to be extended e.g. to polynomials.\r\n * Basic bracketing algorithm\r\n * Also works well in F# with the F# extensions.\r\n* Linear Algebra:\r\n * Native eigenvalue decomposition (EVD) support with our MKL packages *~Marcus Cuda*\r\n * Add missing scalar-vector operations (s-v, s/v, s%v) *~Thomas Ibel*\r\n * Support for new F# 3.1 row/column slicing syntax on matrices\r\n * Matrices learned proper OfColumn/RowVectors, analog also in F#.\r\n * Documentation Fixes *~Robin Neatherway*\r\n * BUG: Fixed exception text message when creating a matrix from enumerables (rows vs columns) *~Thomas Ibel*\r\n * We\u0027re phasing out MathNet.Numerics.IO that used to be included in the main package for matrix file I/O for text and Matlab formats. Use the new .Data.Text and .Data.Matlab packages instead.\r\n* Statistics: Spearman Rank Correlation Coefficient *~Iain McDonald*\r\n* Statistics: Covariance function, in Array-, Streaming- and common Statistics.\r\n* Distributions: Categorical: distribution more consistent, no longer requires normalized pdf/cdf parameters\r\n* Distributions: Categorical: inverse CDF function *~Paul Varkey*\r\n* BUG: Distributions: Fixed static sampling methods of the \u0060Stable\u0060 distribution. *~Artyom Baranovskiy*\r\n* BUG: Fixed a bug in the Gamma Regularized special function where in some cases with large values it returned 1 instead of 0 and vice versa.\r\n* The F# extensions now have a strong name in (and only in) the signed package as well (previously had not been signed). *~Gauthier Segay*\r\n* Evaluate.Polynomial with new overload which is easier to use.\r\n* Fixed a couple badly designed unit tests that failed on Mono.\r\n* Repository now Vagrant-ready for easy testing against recent Mono on Debian.\r\n\r\n### 2.5.0 - 2013-04-14\r\n* See also: [What\u0027s New in Math.NET Numerics 2.5](https://christoph.ruegg.name/blog/new-in-mathnet-numerics-2-5.html)\r\n* Statistics: Empty statistics now return NaN instead of either 0 or throwing an exception. *This may break code in case you relied upon the previous unusual and inconsistent behavior.*\r\n* Linear Algebra: More reasonable ToString behavior for matrices and vectors. *This may break code if you relied upon ToString to export your full data to text form intended to be parsed again later. Note that the classes in the MathNet.Numerics.IO library are more appropriate for storing and loading data.*\r\n* Statistics:\r\n * More consistent behavior for empty and single-element data sets: Min, Max, Mean, Variance, Standard Deviation etc. no longer throw exceptions if the data set is empty but instead return NaN. Variance and Standard Deviation will also return NaN if the set contains only a single entry. Population Variance and Population Standard Deviation will return 0 in this case.\r\n * Reworked order statistics (Quantile, Quartile, Percentile, IQR, Fivenum, etc.), now much easier to use and supporting compatibility with all 9 R-types, Excel and Mathematica. The obsolete Percentile class now leverages the new order statistics, fixing a range check bug as side effect.\r\n * New Hybrid Monte Carlo sampler for multivariate distributions. *~manyue*\r\n * New financial statistics: absolute risk and return measures. *~Phil Cleveland*\r\n * Explicit statistics for sorted arrays, unsorted arrays and sequences/streams. Faster algorithms on sorted data, also avoids multiple enumerations.\r\n * Some statistics like Quantile or empirical inverse CDF can optionally return a parametric function when multiple evaluations are needed, like for plotting.\r\n* Linear Algebra:\r\n * More reasonable ToString behavior for matrices and vectors: \u0060ToString\u0060 methods no longer render the whole structure to a string for large data, among others because they used to wreak havoc in debugging and interactive scenarios like F# FSI. Instead, ToString now only renders an excerpt of the data, together with a line about dimension, type and in case of sparse data a sparseness indicator. The intention is to give a good idea about the data in a visually useful way. How much data is shown can be adjusted in the Control class. See also ToTypeString and ToVector/MatrixString.\r\n * Performance: reworked and tuned common parallelization. Some operations are up to 3 magnitudes faster in some extreme cases. Replaced copy loops with native routines. More algorithms are storage-aware (and should thus perform better especially on sparse data). *~Thomas Ibel, Iain McDonald, Marcus Cuda*\r\n * Fixed range checks in the Thin-QR decomposition. *~Marcus Cuda*\r\n * BUG: Fixed bug in Gram Schmidt for solving tall matrices. *~Marcus Cuda*\r\n * Vectors now implement the BCL IList interfaces (fixed-length) for better integration with existing .Net code. *~Scott Stephens*\r\n * Matrix/Vector parsing has been updated to be able to parse the new visual format as well (see ToMatrixString).\r\n * DebuggerDisplay attributes for matrices and vectors.\r\n * Map/IndexedMap combinators with storage-aware and partially parallelized implementations for both dense and sparse data.\r\n * Reworked Matrix/Vector construction from arrays, enumerables, indexed enumerables, nested enumerables or by providing an init function/lambda. Non-obsolete constructors now always use the raw data array directly without copying, while static functions always return a matrix/vector independent of the provided data source.\r\n * F#: Improved extensions for matrix and vector construction: create, zeroCreate, randomCreate, init, ofArray2, ofRows/ofRowsList, ofColumns/ofColumnsList, ofSeqi/Listi (indexed). Storage-aware for performance.\r\n * F#: Updated map/mapi and other combinators to leverage core implementation, added -nz variants where zero-values may be skipped (relevant mostly for sparse matrices).\r\n * F#: Idiomatic slice setters for sub-matrices and sub-vectors\r\n * F#: More examples for matrix/vector creation and linear regression in the F# Sample-package.\r\n* Control: Simpler usage with new static ConfigureAuto and ConfigureSingleThread methods. Resolved misleading configuration logic and naming around disabling parallelization.\r\n* Control: New settings for linear algebra ToString behavior.\r\n* Fixed range check in the Xor-shift pseudo-RNG.\r\n* Parallelization: Reworked our common logic to avoid expensive lambda calls in inner loops. Tunable.\r\n* F#: Examples (and thus the NuGet Sample package) are now F# scripts prepared for experimenting interactively in FSI, instead of normal F# files. Tries to get the assembly references right for most users, both within the Math.NET Numerics solution and the NuGet package.\r\n* Various minor improvements on consistency, performance, tests, xml docs, obsolete attributes, redundant code, argument checks, resources, cleanup, nuget, etc.\r\n\r\n### 2.4.0 - 2013-02-03\r\n* Drops the dependency on the zlib library. We thus no longer have any dependencies on other packages. *~Marcus Cuda, Thomas Ibel*\r\n* Adds Modified Bessel \u0026 Struve special functions *~Wei Wu*\r\n* BUG: Fixes a bug in our iterative kurtosis statistics formula *~Artyom Baranovskiy*\r\n* Linear Algebra: Performance work, this time mostly around accessing matrix rows/columns as vectors. Opting out from targeted patching in our matrix and vector indexers to allow inlining.\r\n* Linear Algebra: Fixes an issue around Thin-QR solve *~Marcus Cuda*\r\n* Linear Algebra: Simplifications around using native linear algebra providers (see Math.NET Numerics With Native Linear Algebra)\r\n* F#: Adds the BigRational module from the F# PowerPack, now to be maintained here instead. *~Gustavo Guerra*\r\n* F#: Better support for our Complex types (close to the F# PowerPack Complex type) *~Gustavo Guerra*\r\n\r\n### 2.3.0 - 2013-11-25\r\n* Portable Library: Adds support for WP8 (.Net 4.0 and higher, SL5, WP8 and .NET for Windows Store apps)\r\n* Portable Library: New: portable build also for F# extensions (.Net 4.5, SL5 and .NET for Windows Store apps)\r\n* Portable Library: NuGet: portable builds are now included in the main packages, no more need for special portable packages\r\n* Linear Algebra: Continued major storage rework, in this release focusing on vectors (previous release was on matrices)\r\n* Linear Algebra: Thin QR decomposition (in addition to existing full QR)\r\n* Linear Algebra: Static CreateRandom for all dense matrix and vector types\r\n* Linear Algebra: F#: slicing support for matrices and vectors\r\n* Distributions: Consistent static Sample methods for all continuous and discrete distributions (was previously missing on a few)\r\n* F#: better usability for random numbers and distributions.\r\n* F# extensions are now using F# 3.0\r\n* Updated Intel MKL references for our native linear algebra providers\r\n* Various bug, performance and usability fixes\r\n"},{"uri":"https://numerics.mathdotnet.com/Users.html","title":"Who is using Math.NET Numerics?\r\n","content":"Who is using Math.NET Numerics?\r\n===============================\r\n\r\n*This page collects anything that references and/or uses Math.NET Numerics.\r\nFeel free to [add, edit or remove your own work](https://github.com/mathnet/mathnet-numerics/blob/master/docs/content/Users.md) by submitting a pull request.*\r\n\r\nOpen Source\r\n-----------\r\n\r\n* [MyMediaLite Recommender System Library](https://www.ismll.uni-hildesheim.de/mymedialite/)\r\n* [FermiSim, studying potential solutions to the Fermi paradox via computational simulation of models for space colonisation](https://launchpad.net/fermisim)\r\n* [Three-Dimensional Model Shape Description and Retrieval Based on LightField Descriptors](https://code.google.com/p/lightfieldretrieval/)\r\n* [Virtual Photonics Technology Initiative](https://virtualphotonics.codeplex.com/)\r\n* [SharpFE: a lightweight, expandable finite element solver for .net](https://github.com/iainsproat/SharpFE)\r\n* [FsLab: Machine Learning and Data Science with F#](https://fslab.org/)\r\n* [Simple FM Matrix](https://cs.mcgill.ca/~ryang6/simplefmmatrix/)\r\n* [mathlib.net](https://mathlibproject.codeplex.com/)\r\n* [PhysicsPad](https://github.com/Amichai/PhysicsPad)\r\n* [DRFCSharp: Discriminative Random Fields implementation for C#](https://github.com/exitmouse/drfcsharp)\r\n* [SharpBench: Benchmarking system for Mono/.Net](https://github.com/ranma42/SharpBench)\r\n* [Behavioral Rating of Dancing Human Crowds based on Motion Patterns](https://emotiondetection.codeplex.com/)\r\n* [NPSS Framework for numerical computations of Laguerre series](https://www.openhub.net/p/npss)\r\n* [FIRST Robotics Scout App](https://frcscout.codeplex.com/)\r\n* [Improvisation: Automatic Music Composition and Melody Generation](https://github.com/ArmenAg/Improvisation)\r\n* [Epicycle Math Library](https://github.com/open-epicycle/Epicycle.Math-cs)\r\n* [LitePlacer machine user interface and control software](https://github.com/jkuusama/LitePlacer)\r\n* [Computator.NET](https://github.com/PawelTroka/Computator.NET)\r\n* [EV2020: Project Electric Transportation 2020](https://github.com/EraYaN/EV202)\r\n* [HexLight GUI: RGB LED controller](https://github.com/jorticus/hexlight-gui)\r\n* [HydroNumerics](https://code.google.com/archive/p/hydronumerics/)\r\n* [SolidWorks to URDF Exporter](https://bitbucket.org/brawner/sw2urdf)\r\n* [Reinforcement Simulator](https://github.com/lg-octaviano/Reinforcement_Simulator)\r\n* [Maintenance Game](https://github.com/KaptenJon/MaintenanceGame)\r\n* [Monica](https://github.com/zhuazhua/Monica)\r\n* [Math.Net PowerShell](https://mathnetpowershell.codeplex.com/) (unaffiliated)\r\n* [Math.NET Symbolics](https://symbolics.mathdotnet.com) and other [Math.NET](https://www.mathdotnet.com) projects.\r\n\r\nClosed Source\r\n-------------\r\n\r\n* [C# Pad](https://www.csharppad.com)\r\n* [Colectica](https://www.colectica.com) Data Documentation\r\n* [Instarange Simulation](https://instarange.com) by Instarange (Pty) Ltd\r\n* [SpectraFox](https://www.spectrafox.com/) STM / AFM spectroscopy analysis\r\n* [Colymp](https://colymp.com/) Color Management Software\r\n* [ILNumerics](https://ilnumerics.net/)\r\n* [GazeSpeaker](https://www.gazespeaker.org) Free software to help people with disabilities\r\n* [ModVal.org](https://www.modval.org) Quant model repository for regulatory and internal model validation.\r\n* [Passivefilter](https://sites.google.com/site/passivefilter/home) Filter synthesis\r\n* [Qunatellia](https://www.quantellia.com) World Modeler\r\n* [Umberto NXT](https://www.umberto.de) Carbon footprint, resource efficiency, life-cycle assessment, eco-efficiency.\r\n* Agilent Waveform Creator: [Easily create custom Waveform plug-ins with Waveform Creator application software](https://cp.literature.agilent.com/litweb/pdf/5991-3203EN.pdf) (PDF)\r\n* Multiple medical hearing care companies\r\n\r\nBlogs, Tutorials \u0026 Examples\r\n---------------------------\r\n\r\n* [Yin Zhu: Tutorial: Using Math.NET Numerics in F#](https://msdn.microsoft.com/en-us/library/hh304363.aspx)\r\n* [Don Syme: Getting Started with Math.NET and F# Programming](https://blogs.msdn.com/b/dsyme/archive/2012/07/06/getting-started-with-math-net-and-f-programming.aspx)\r\n* [Libor Tinka: Linear and Nonlinear Least-Squares with Math.NET](https://www.imagingshop.com/articles/least-squares)\r\n* [Carl Nolan: Co-occurrence Approach to an Item Based Recommender](https://code.msdn.microsoft.com/Co-occurrence-Approach-to-57027db7)\r\n* [Gustavo Guerra: F# as a Octave/Matlab Replacement for Machine Learning](https://functionalflow.co.uk/blog/2011/10/27/f-as-a-octavematlab-replacement-for-machine-learning/)\r\n* [Mathias Brandewinder: Simplify data with SVD and Math.NET in F#](https://clear-lines.com/blog/post/Simplify-data-with-SVD-and-MathNET-in-FSharp.aspx)\r\n* [Mathias Brandewinder: Recommendation Engine using Math.NET, SVD and F#](https://clear-lines.com/blog/post/Recommendation-Engine-with-SVD-and-MathNET-in-FSharp.aspx)\r\n* [Thomas Jungblut: Stochastic Logistic Regression in F#](https://codingwiththomas.blogspot.ch/2014/05/stochastic-logistic-regression-in-f.html)\r\n* [Calvin Bottoms: Set-Based Operations: They\u2019re Not Just For Databases](https://calvinbottoms.blogspot.ch/2012/01/set-based-operations-theyre-not-just.html)\r\n* [Chao-Jen Chen: F#: Simulate entire GBM path](https://programmingcradle.blogspot.ch/2012/09/f-simulate-entire-gbm-path.html)\r\n* [Chao-Jen Chen: F#: K-S test on final prices of GBM paths ](https://programmingcradle.blogspot.ch/2012/09/f-k-s-test-on-final-prices-of-gbm-paths.html)\r\n* [Dawid Kowalski: F#, Deedle and Computational Investing](https://dkowalski.com/blog/archive/2014/01/11/f-deedle-and-computational-investing.aspx)\r\n* [Jason Fossen: PowerShell for Math.NET Numerics](https://cyber-defense.sans.org/blog/2015/06/27/powershell-for-math-net-numerics)\r\n* [Jason Fossen: TrueRNG Random Numbers with PowerShell and Math.NET Numerics](https://cyber-defense.sans.org/blog/2015/07/24/truerng-usb-random-numbers-powershell-mathnet-numerics)\r\n* [Thomasz Jaskula: Data Science tools in F# through univariante linear regression](https://jaskula.fr/blog/2015/12-02-data-science-tools-in-f-through-univariante-linear-regression/)\r\n* [Christoph R\u00FCegg: Linear Regression With Math.NET Numerics](https://christoph.ruegg.name/blog/linear-regression-mathnet-numerics.html)\r\n\r\nBooks\r\n-----\r\n\r\n* Expert F# 3.0 *by Don Syme, Adam Granicz, Antonio Cisternino*. Apress.\r\n* F# for Quantitative Finance *by Johan Astborg*. Packt Publishing.\r\n* F# Deep Dives *by Tomas Petricek, Philip Trelford*. Manning Publications.\r\n* Computer Graphics: Principles and Practices *by John F. Hughes, Andries van Dam, Morgan McGuire, David F. Sklar, James D. Foley, Steven K. Feiner, Kurt Akeley*. Addison-Wesley Professional, 3rd edition.\r\n* Machine Learning Projects for .NET Developers *by Matthias Brandewinder*. Apress.\r\n* C# for Financial Markets *by Daniel J. Duffy, Andrea Germani*. Wiley Finance.\r\n\r\nPapers and Thesis\r\n-----------------\r\n\r\n* Dalchau, Neil; Grant, Paul K.; Vaidyanathan, Prashant; Spaccasassi, Carlo; Gravill, Colin; Phillips, Andrew (2019). *Scalable dynamic characterization of synthetic gene circuits.* Microsoft Research. DOI 10.1101/635672.\r\n* Gao, Peichao; Cushman, Samuel A.; Liu, Gang; Ye, Sijing; Shen, Shi; Cheng, Changxiu (2019). *FracL: A Tool for Characterizing the Fractality of Landscape Gradients from a New Perspective.* MDPI Iternationa Journal of Geo-Information. DOI 10.3390/ijgi8100466.\r\n* Vlasenko, Alexander; Vlasenko, Nataliia; Vynokurova, Olena; Bodyanskiy, Yevgeniy; Peleshko, Dmytro (2019). *A Novel Ensemble Neuro-Fuzzy Model for Financial Time Series Forecasting.* MDPI data. DOI 10.3390/data4030126.\r\n* Falke, Martin; H\u00F6glund, Lucas (2019). *Implementing gaze tracking with a simple web camera.* KTH School of Electrical Engineering and Computer Science, Stockholm.\r\n* Rottsch\u00E4fer, Marcus Philip (2019). *Simultaneous Visual Analysis of Multidimensional Data and Attributes.* Institute for Visualization and Interactive Systems, University of Stuttgart.\r\n* Azimov, R., Grigorev, S. (2019). *Path Querying with Conjunctive Grammars by Matrix Multiplication.* Program Comput Soft 45, 357\u2013364. DOI 10.1134/S0361768819070041\r\n* Honfi, D., Micskei, Z. (2019). *Classifying generated white-box tests: an exploratory study.* Software Qual J 27, 1339\u20131380. DOI 10.1007/s11219-019-09446-5.\r\n* Sowa, Marcin (2018). *A Harmonic Balance Methodology for Circuits with Fractional and Nonlinear Elements.* Circuits Syst Signal Process 37:4695\u20134727. DOI 10.1007/s00034-018-0794-8.\r\n* Schaffranek, Richard (2015). *Parallel planning - An experimental study in spectral graph matching.* Vienna University of Technology. Proceedings of the 10th International Space Syntax Symposium.\r\n* De Feber, Max (2017). *Real-time numerical modeling of subsea cable dynamics - Visualized in Augmented Reality.* Offshore \u0026 Dredging Engineering, Delft University of Technology.\r\n* Nkurikiyeyezu, K.; Ahishakiye, F.; Nsengimana, C.; Ntagwirumugara, E. (2015). *Toolkits for Real Time Digital Audio Signal Processing Teaching Laboratory.* University of Rwanda. Journal of Signal and Information Processing. DOI 10.4236/jsip.2015.62009\r\n* Czarnowska, Lucyna; Litwin, Wojciech; Stanek, Wojciech (2015). *Selection of Numerical Methods and their Application to the Thermo-Ecological Life Cycle Cost of Heat Exchanger Components*. Silesian University of Technology.\r\n* Schmollinger, Stefan; M\u00FClhaus, Timo; et al (2014). *Nitrogen-Sparing Mechanisms in Chlamydomonas Affect the Transcriptome, the Proteome, and Photosynthetic Metabolism.* The Plant Cell. DOI 10.1105/tpc.113.122523\r\n* Mettler, Tabea; M\u00FClhaus, Timo; et al (2014). *Systems Analysis of the Response of Photosynthesis, Metabolism, and Growth to an Increase in Irradiance in the Photosynthetic Model Organism Chlamydomonas reinhardtii.* The Plant Cell. DOI 10.1105/tpc.114.124537.\r\n* Blah\u00FAt, Jozef (2014). *Design and Implementation of Application for Measured Data Processing*. Brno University of Technology.\r\n* Mueller, Caitlin; Ochsendorf John (2013). *From Analysis to Design: A New Computational Strategy for Structural Creativity.* Massachusetts Institute of Technology. 2nd International Workshop on Design in Civil and Environmental Engineering.\r\n* Puwalowski, Mateusz (2013). *Ukryte Indeksowanie Semantyczne.* Uniwersytet Gdanski.\r\n* Botter, R (2013). *Effici\u00EBnt begroten met historische projectgegevens.* Technische Universiteit Eindhoven.\r\n* Parma, Alessio (2013). *Una libreria per la simulazione a eventi discreti in .NET.* Universit\u00E0 Degli Studi Di Genova.\r\n* Singh, Rohit; Gulwani, Sumit; Rajamani Sriram (2012). *Automatically Generating Algebra Problems.* Microsoft Research. Association for the Advancement of Artificial Intelligence.\r\n* Grahl Pereira, Andr\u00E9; Petry, Adriano (2012). *Data Assimilation using NeuroEvolution of Augmenting Topologies.* IJCNN. WCCI 2012 IEEE World Congress on Computational Intelligence.\r\n* Lauppe, Joost (2012). *Reinforcement Toolbox: A Parametric Reinforcement Modeling Tool for Curved Surface Structures.* Delft University of Technology.\r\n* Lundstr\u00F6m, Lukas (2012). *Weather data for building simulation: New actual weather files for North Europe combining observed weather and modeled solar radiation.* School of Sustainable Development of Society and Technology, HST.\r\n* AT Council (2012). *Seismic Performance Assessment of Buildings Volume 2 - Implementation Guide.* FEMA, U.S. Department of Homeland Security.\r\n* Ma, Jiangshan (2012). *Hyperpath-based Strategic Route Guidance Considering Travel Time Uncertainty.* Transportation Studies Unit, Tokyo Institute of Transportation.\r\n* Fisher, Michael (2012). *Research and Development of a VST Plugin for the Autonomous Post Production of a Stereo Piano Recording.* University of Huddersfield.\r\n* Williams, Liam (2012). *Spotting The Wisdom In The Crowds.* Imperial College London.\r\n* Schr\u00E4der, Niklas (2011). *Detecting falls and poses in image silhouettes (M.Sc).* Chalmers University of Technology, Gothenburg, Sweden. ISSN 1652-8557.\r\n* Nelson, Peter (2011). *3D Mapping for Robotic Search and Rescue.* New College.\r\n* Adelson, Michael (2011). *Emotiv Experimenter: An experimentation and mind-reading application for the Emotiv EPOC.* Princeton University.\r\n* Schindlberger, Michael (2011). *Elastic Properties of Growing 2D Foam (M.Sc).* University of Zurich.\r\n* Krejcar, Ondrej; Jirka, Jakub; Janckulik, Dalibor (2011). *Use of Mobile Phones as Intelligent Sensors for Sound Input Analysis and Sleep State Detection.* Sensors (11): 6037\u20136055. ISSN 1424-8220.\r\n* Keglevic, Manuel; Schulz, Thomas (2011). *NoNoise - Music Library Visualization.* Vienna University of Technology.\r\n* Kraus, Jan; Bubla, Viktor; Kukacka, Leos (2011). *Data Modeling for Reduction of Volume in Large Archives of Power Quality Data.* 21st International Conference on Electricity Distribution. TUL CZ.\r\n* Ferreira, Andr\u00E9 Filipe Mateus. *SoundLog: Make More Noise (M.Sc).* Universidade T\u00E9cnica de Lisboa.\r\n* Nunes, Jos\u00E9; S\u00E1, Luis; Perdig\u00E3o, Fernando (2011). *Talking Avatar for Web-based Interfaces.* Instituto de Telecomunica\u00E7\u00F5es, Coimbra, Portugal.\r\n* Dostra\u0161il, Pavel; Jir\u00E1sko, Petr (2011). *Productive Design and Calculation of Intermittent Mechanisms with Radial Parallel Cams.* International Journal of Mechanical, Aerospace, Industrial, Mechatronic and Manufacturing Engineering Vol:5, No:11, 2011.\r\n* Miller, Justin (2010). *Design of a Wireless Acquisition System for a Digital Stethoscope (B.Sc).* University of Southern Queensland.\r\n* Skrehota, Ondrej (2010). *Quantitative structure-property relationship modeling algorithms, challenges and IT solutions.* Masaryk University.\r\n* L\u00CD\u0160KA, Ondrej; \u017DIDEK, Kamil (2010). *Accelerometers usability for danger tilt off-highway vehicles and signal filtration with kalman filter.* Journal of applied science in the thermodynamics and fluid mechanics 4 (2): 1\u20136. ISSN 1802-9388.\r\n* Team Limawai (2010). *Ka\u0060imiolakai ROV.* 2010 MATE International UROV Competition. Kapi\u0060olani Community College.\r\n* Hebel, Tobias (2010). *Location Provider.* Universit\u00E4t Koblenz Landau.\r\n* Bischoff, Sebastian (2009). *Konzeption und Umsetzung einer RIA zur untersuchungsbegleitenden Erfassung von RNFLT-Scans und Untersuchung von Klassifikatoren f\u00FCr die diagnostische Unterst\u00FCtzung bei neurodegenerativen Erkrankungen am Beispiel der Multiplen Sklerose.* Fachhochschule Brandenburg.\r\n"}] \ No newline at end of file diff --git a/logo.png b/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..a8d70ce696b1b34dd4fc5423b040fc647d88cf92 GIT binary patch literal 16028 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®(MPJwGr|)Nfi7kQO#9cl4leujj2% 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