From 035ca0ba6d6c6caf4923b35ab04de743e391c7b4 Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Tue, 21 Jan 2014 18:33:51 +0100 Subject: [PATCH] Docs: initial setup --- MathNet.Numerics.NativeProviders.sln | 5 - MathNet.Numerics.Net35Only.sln | 12 -- MathNet.Numerics.Portable.sln | 12 -- MathNet.Numerics.sln | 21 +- build.fsx | 10 +- docs/content/RandomAndDistributions.fsx | 258 ++++++++++++++++++++++++ docs/content/index.fsx | 71 +++++++ docs/files/img/logo.png | Bin 0 -> 16028 bytes docs/tools/build-docs.fsx | 89 ++++++++ docs/tools/packages.config | 7 + docs/tools/templates/template.cshtml | 61 ++++++ 11 files changed, 514 insertions(+), 32 deletions(-) create mode 100644 docs/content/RandomAndDistributions.fsx create mode 100644 docs/content/index.fsx create mode 100644 docs/files/img/logo.png create mode 100644 docs/tools/build-docs.fsx create mode 100644 docs/tools/packages.config create mode 100644 docs/tools/templates/template.cshtml diff --git a/MathNet.Numerics.NativeProviders.sln b/MathNet.Numerics.NativeProviders.sln index 6b37794a..98886230 100644 --- a/MathNet.Numerics.NativeProviders.sln +++ b/MathNet.Numerics.NativeProviders.sln @@ -20,11 +20,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Numerics", "src\Numerics\Nu EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests-MKL", "src\UnitTests\UnitTests-MKL.csproj", "{3515A344-AB5F-41C7-A14C-04A79B3FFAB1}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NuGet", ".nuget", "{2D8D8FBA-6B67-4F44-87D3-7D751FF7AFE2}" - ProjectSection(SolutionItems) = preProject - .nuget\packages.config = .nuget\packages.config - EndProjectSection -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/MathNet.Numerics.Net35Only.sln b/MathNet.Numerics.Net35Only.sln index 7950ac38..4f063d42 100644 --- a/MathNet.Numerics.Net35Only.sln +++ b/MathNet.Numerics.Net35Only.sln @@ -17,18 +17,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Numerics-Net35", "src\Numer EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests-Net35", "src\UnitTests\UnitTests-Net35.csproj", "{9014A0CE-725D-4718-918C-923C0CA19FEE}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{A4A66FA9-C00C-4D5C-A776-27516EA0C536}" - ProjectSection(SolutionItems) = preProject - build.fsx = build.fsx - build\NuGet\FSharp\MathNet.Numerics.FSharp.nuspec = build\NuGet\FSharp\MathNet.Numerics.FSharp.nuspec - build\NuGet\FSharp.Signed\MathNet.Numerics.FSharp.Signed.nuspec = build\NuGet\FSharp.Signed\MathNet.Numerics.FSharp.Signed.nuspec - build\NuGet\Numerics\MathNet.Numerics.nuspec = build\NuGet\Numerics\MathNet.Numerics.nuspec - build\NuGet\Numerics.Signed\MathNet.Numerics.Signed.nuspec = build\NuGet\Numerics.Signed\MathNet.Numerics.Signed.nuspec - build\NuGet\nuget-signed.proj = build\NuGet\nuget-signed.proj - build\NuGet\nuget.proj = build\NuGet\nuget.proj - .nuget\packages.config = .nuget\packages.config - EndProjectSection -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/MathNet.Numerics.Portable.sln b/MathNet.Numerics.Portable.sln index 4f05b505..8ec5eb05 100644 --- a/MathNet.Numerics.Portable.sln +++ b/MathNet.Numerics.Portable.sln @@ -52,18 +52,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Numerics-Net35", "src\Numer EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests-Net35", "src\UnitTests\UnitTests-Net35.csproj", "{9014A0CE-725D-4718-918C-923C0CA19FEE}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{A4A66FA9-C00C-4D5C-A776-27516EA0C536}" - ProjectSection(SolutionItems) = preProject - build.fsx = build.fsx - build\NuGet\FSharp\MathNet.Numerics.FSharp.nuspec = build\NuGet\FSharp\MathNet.Numerics.FSharp.nuspec - build\NuGet\FSharp.Signed\MathNet.Numerics.FSharp.Signed.nuspec = build\NuGet\FSharp.Signed\MathNet.Numerics.FSharp.Signed.nuspec - build\NuGet\Numerics\MathNet.Numerics.nuspec = build\NuGet\Numerics\MathNet.Numerics.nuspec - build\NuGet\Numerics.Signed\MathNet.Numerics.Signed.nuspec = build\NuGet\Numerics.Signed\MathNet.Numerics.Signed.nuspec - build\NuGet\nuget-signed.proj = build\NuGet\nuget-signed.proj - build\NuGet\nuget.proj = build\NuGet\nuget.proj - .nuget\packages.config = .nuget\packages.config - EndProjectSection -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/MathNet.Numerics.sln b/MathNet.Numerics.sln index aba5fee0..ee57bea7 100644 --- a/MathNet.Numerics.sln +++ b/MathNet.Numerics.sln @@ -35,13 +35,30 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{A4A66FA9-C00C-4D5C-A776-27516EA0C536}" ProjectSection(SolutionItems) = preProject build.fsx = build.fsx + .nuget\packages.config = .nuget\packages.config + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{039229DA-AFDA-48DB-B7FC-B064691DEE96}" + ProjectSection(SolutionItems) = preProject + docs\content\index.fsx = docs\content\index.fsx + docs\content\RandomAndDistributions.fsx = docs\content\RandomAndDistributions.fsx + docs\tools\templates\template.cshtml = docs\tools\templates\template.cshtml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NuGet", "NuGet", "{8A295380-F19B-460C-9794-2EF1B67E5483}" + ProjectSection(SolutionItems) = preProject build\NuGet\FSharp\MathNet.Numerics.FSharp.nuspec = build\NuGet\FSharp\MathNet.Numerics.FSharp.nuspec build\NuGet\FSharp.Signed\MathNet.Numerics.FSharp.Signed.nuspec = build\NuGet\FSharp.Signed\MathNet.Numerics.FSharp.Signed.nuspec build\NuGet\Numerics\MathNet.Numerics.nuspec = build\NuGet\Numerics\MathNet.Numerics.nuspec build\NuGet\Numerics.Signed\MathNet.Numerics.Signed.nuspec = build\NuGet\Numerics.Signed\MathNet.Numerics.Signed.nuspec build\NuGet\nuget-signed.proj = build\NuGet\nuget-signed.proj build\NuGet\nuget.proj = build\NuGet\nuget.proj - .nuget\packages.config = .nuget\packages.config + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{DB89F4DB-5204-4B38-B9F5-FE11E69D32AD}" + ProjectSection(SolutionItems) = preProject + docs\tools\build-docs.fsx = docs\tools\build-docs.fsx + docs\tools\packages.config = docs\tools\packages.config EndProjectSection EndProject Global @@ -96,5 +113,7 @@ Global {DAF07AA8-C5C9-4963-98F7-2C3285064DAD} = {4D50FB34-10BC-495A-8B2F-482E34B4D771} {8239A6FF-1EF3-4DA4-A860-95C392DD6899} = {49EE74BD-301F-4C3B-B76A-07F90CC88CE7} {BC81EA37-8EE6-4BF9-B8A9-B30497AEF8B1} = {49EE74BD-301F-4C3B-B76A-07F90CC88CE7} + {8A295380-F19B-460C-9794-2EF1B67E5483} = {A4A66FA9-C00C-4D5C-A776-27516EA0C536} + {DB89F4DB-5204-4B38-B9F5-FE11E69D32AD} = {A4A66FA9-C00C-4D5C-A776-27516EA0C536} EndGlobalSection EndGlobal diff --git a/build.fsx b/build.fsx index 2edccbbd..2296da58 100644 --- a/build.fsx +++ b/build.fsx @@ -19,7 +19,7 @@ Target "RestorePackages" RestorePackages Target "AssemblyInfo" DoNothing Target "Prepare" DoNothing -"Clean" ==> "Restorepackages" ==> "AssemblyInfo" ==> "Prepare" +"Clean" ==> "RestorePackages" ==> "AssemblyInfo" ==> "Prepare" // BUILD @@ -52,7 +52,13 @@ Target "Test" (fun _ -> // DOCUMENTATION -Target "Docs" DoNothing +Target "Docs" (fun _ -> + executeFSIWithArgs "docs/tools" "build-docs.fsx" ["--define:RELEASE"] [] |> ignore +) + +Target "DocsDev" (fun _ -> + executeFSIWithArgs "docs/tools" "build-docs.fsx" [] [] |> ignore +) "Build" ==> "Docs" diff --git a/docs/content/RandomAndDistributions.fsx b/docs/content/RandomAndDistributions.fsx new file mode 100644 index 00000000..4af5086c --- /dev/null +++ b/docs/content/RandomAndDistributions.fsx @@ -0,0 +1,258 @@ +(*** hide ***) +#I "../../out/lib/net40" +#r "MathNet.Numerics.dll" +#r "MathNet.Numerics.FSharp.dll" + +(** +Random Numbers and Probability Distributions +============================================ + +The .Net Framework base class library 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 +in randomness, bias, sequence length and performance. All these classes +inherit from `System.Random` so you can use them as a drop-in replacement +even in third-party code. + +All random number generators (RNG) generate numbers in a more-or-less uniform +distribution. In practice you often need to sample random numbers with a different +distribution, like a Gaussian or Poisson. You can do that with one of our probability +distribution classes, or in F# also using the `Sample` module. Once parametrized, +the distribution classes also provide a variety of other functionality around probability +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: + + [lang=csharp] + using MathNet.Numerics.Random; + using MathNet.Numerics.Distributions; + +Or in F#: +*) + +open MathNet.Numerics.Random +open MathNet.Numerics.Distributions + +(** +Random Number Generators +------------------------ + +Let's sample a few uniform random values using Mersenne Twister in C#: + + [lang=csharp] + var rng = new MersenneTwister(42); + int randomInt = rng.Next(); + double randomDouble = rng.NextDouble(); + +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`: +*) + +let rng = MersenneTwister(42) +let rngEx = Random.mersenneTwisterSeed 42 +let randomInt = rng.Next() + +(** +If you have used `System.Random` before, you may remember that it only offers `Next` methods +to sample integers, and `NextDouble` for floating point numbers in the [0,1) interval. +Did you ever have a need to generate numbers of the full integer range including negative numbers, +or a `System.Decimal`? Extending discrete random numbers to different ranges or types is non-trivial +if the distribution should still be uniform over the chosen range. That's why we've added a few extensions +methods which are available on all RNGs (including `System.Random` itself): +*) + +let values = + ( rng.Next(), // built-in: int32 in the range [0, Int.MaxValue) + rng.NextInt64(), // int64 in the range [0, Long.MaxValue) + rng.NextFullRangeInt32(), // int32 in the range [Int.MinValue, Int.MaxValue] + rng.NextFullRangeInt64(), // int64 in the range [Long.MinValue, Long.MaxValue] + rng.NextDouble(), // built-in: double in the range [0.0, 1.0) + rng.NextDecimal() ) // decimal in then range [0.0, 1.0) + +(** +The following custom RNGs are currently available in Math.NET Numerics: + +* `MersenneTwister`: Mersenne Twister 19937 generator +* `Xorshift`: Multiply-with-carry XOR-shift generator +* `Mcg31m1`: Multiplicative congruental generator using a modulus of 2^31-1 and a multiplier of 1132489760 +* `Mcg59`: Multiplicative congruental generator using a modulus of 2^59 and a multiplier of 13^13 +* `WH1982`: Wichmann-Hill's 1982 combined multiplicative congruental generator +* `WH2006`: Wichmann-Hill's 2006 combined multiplicative congruental generator +* `Mrg32k3a`: 32-bit combined multiple recursive generator with 2 components of order 3 +* `Palf`: Parallel Additive Lagged Fibonacci generator +* `SystemCryptoRandomNumberGenerator`: Using the RNGCryptoServiceProvider of the .Net Framework. *Not available in portable builds.* + +Seeds and Thread Safety +----------------------- + +Other than for cryptographic random numbers where you'd never want to provide +a seed, all other RNGs can be initialized with a custom seed. In the code sample +above we've used `42` as seed. The same seed causes the same number sequence +to be generated, which can be very useful if you need results to be reproducible, +e.g. in testing/verification. + +If no seed is provided, `System.Random` uses a time based seed equivalent to the +one below. This means that all instances created within a short timeframe +(which typically spans about a thousand CPU clock cycles) will generate +exactly the same sequence. This can happen easily e.g. in parallel computing +and is often unwanted. That's why all number generators created using +Math.NET Numerics routines are by default initialized with a seed that combines +the time with a Guid (which are supposed to be generated uniquely, worldwide). +*) + +let someTimeSeed = RandomSeed.Time() +let someGuidSeed = RandomSeed.Guid() + +(** +Note that the generators should be reused when generating multiple numbers. +If you'd create a new generator each time, the numbers it generates would be +exactly as random as your seed - and thus not very random at all. +However, generators are not automatically thread-safe in .Net. They *are* thread-safe +when created using Math.NET Numerics by default, but that can be controlled either by a +boolean argument at creation or by setting `Control.ThreadSafeRandomNumberGenerators`. +*) + +let a = Random.system () +let b = Random.systemSeed (RandomSeed.Guid()) +let c = Random.crypto () +let d = Random.mersenneTwister () +let e = Random.mersenneTwisterWith 1000 true (* thread-safe *) +let f = Random.xorshift () +let g = Random.xorshiftCustom someTimeSeed false 916905990L 13579L 362436069L 77465321L +let h = Random.wh2006 () +let i = Random.palf () + +(** +Probability Distributions +------------------------- + +For non-uniform random number generation you can use one the wide range of probability +distributions in the `MathNet.Numerics.Distributions` namespace. + +There are many ways to parametrize a distribution in the literature. When using the +default constructor, read carefully which parameters it requires. For distributions where +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: + + [lang=csharp] + 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. A few more examples, this time in F#: +*) + +// some probability distributions +let normal = Normal.WithMeanVariance(3.0, 1.5, g) +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()) + +// sample some random rumbers from these distributions +let continuous = + [ yield normal.Sample() + yield exponential.Sample() + yield! gamma.Samples() |> Seq.take 10 ] + +let discrete = + [ poisson.Sample() + poisson.Sample() + geometric.Sample() ] + +// direct sampling (without creating a distribution object) +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 w = Rayleigh.Sample(c, 1.5) +let x = Hypergeometric.Sample(h, 100, 20, 5) + +(** +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. +*) + +// 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) (* invcdf *) + +// 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) + +(** +Some of the distributions also have routines for maximum-likelihood parameter +estimation from a set of samples: +*) + +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#: + + [lang=csharp] + 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(); + +Let's do some random walks, using distributions and random sources defined above (TODO: Graph): +*) + +Seq.scan (+) 0.0 (normal.Samples()) |> Seq.take 10 |> Seq.toArray +Seq.scan (+) 0.0 (Sample.normalSeq 0.0 0.5 a) |> Seq.take 10 |> Seq.toArray + +(** +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: +*) + +/// 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 + +/// Exactly the same also works with functions generating full sequences +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 + +// Taking some samples from the composed function +Seq.take 10 (s2s (Random.system())) |> Seq.toArray + +// The random walk from above, but this time using the composition from above +Seq.scan (+) 0.0 (s1s a) |> Seq.take 10 |> Seq.toArray diff --git a/docs/content/index.fsx b/docs/content/index.fsx new file mode 100644 index 00000000..b8667e58 --- /dev/null +++ b/docs/content/index.fsx @@ -0,0 +1,71 @@ +(*** hide ***) +#I "../../out/lib/net40" +#r "MathNet.Numerics.dll" +#r "MathNet.Numerics.FSharp.dll" + +(** +Getting Started +=============== + +Installation Instructions +------------------------- + +The recommended way to get Math.NET Numerics is to use NuGet. The following packages are provided and maintained in the public [NuGet Gallery](https://nuget.org/profiles/mathnet/): + +- `MathNet.Numerics` - core package, including .Net 4, .Net 3.5 and portable/PCL builds +- `MathNet.Numerics.FSharp` - optional extensions for a better F# experience +- `MathNet.Numerics.Data.Text` - optional extensions for text-based matrix input/output +- `MathNet.Numerics.Data.Matlab` - optional extensions for MATLAB matrix file input/output +- `MathNet.Numerics.MKL.Win-x86` - optional Linear Algebra MKL native provider +- `MathNet.Numerics.MKL.Win-x64` - optional Linear Algebra MKL native provider +- `MathNet.Numerics.Signed` - strong-named version of the core package *(not recommended)* +- `MathNet.Numerics.FSharp.Signed` - strong-named version of the F# package *(not recommended)* + +Alternatively you can also download the binaries in Zip packages, available on [CodePlex](http://mathnetnumerics.codeplex.com/releases): + +- Binaries - core package and F# extensions, including .Net 4, .Net 3.5 and portable/PCL builds. +- Signed Binaries - strong-named version of the core package *(not recommended)*. + +Supported Platforms: + +- .Net 4.0, .Net 3.5 and Mono: Windows, Linux and Mac. +- PCL Portable Profiles 47 and 136: Silverlight 5, Windows Phone 8, .NET for Windows Store apps (Metro). +- PCL/Xamarin: Andoid, iOS + +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 Math.NET Numerics locally either using Visual Studio or manually with the build scripts. + +* The Visual Studio solutions should build out of the box, without any preparation steps or package restores. +* Instead of a compatible IDE you can also build the solutions with `msbuild`, or on Mono with `xbuild`. +* The full build including unit tests, docs, NuGet and Zip packages is using [FAKE](http://fsharp.github.io/FAKE/). + +### How to build with MSBuild/XBuild + + [lang=sh] + msbuild MathNet.Numerics.sln # only build for .Net 4 (main solution) + msbuild MathNet.Numerics.Net35Only.sln # only build for .Net 3.5 + msbuild MathNet.Numerics.Portable.sln # full build with .Net 4, 3.5 and PCL profiles + xbuild MathNet.Numerics.sln # build with Mono, e.g. on Linux or Mac + +### How to build with FAKE + + [lang=sh] + build.cmd # normal build (.Net 4.0), run unit tests + ./build.sh # normal build (.Net 4.0), run unit tests - on Linux or Mac + + build.cmd Build # normal build (.Net 4.0) + build.cmd Build full # full build (.Net 3.5, 4.0, PCL) + build.cmd Build net35 # compatibility build (.Net 3.5) + + build.cmd Test # normal build (.Net 4.0), run unit tests + build.cmd Test full # full build (.Net 3.5, 4.0, PCL), run all unit tests + build.cmd Test net35 # compatibility build (.Net 3.5), run unit tests + + build.cmd Clean # cleanup build artifacts + build.cmd Docs # generate documentation, normal build + build.cmd NuGet # generate NuGet packages, full build + +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 `msbuild` directly. +*) diff --git a/docs/files/img/logo.png b/docs/files/img/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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 +// otherwise, use the current 'output' directory. +#if RELEASE +let root = website +#else +let root = "file://" + (__SOURCE_DIRECTORY__ @@ "../../out/docs") +#endif + +// Paths with template/source/output locations +let bin = __SOURCE_DIRECTORY__ @@ "../../out/lib/net40" +let content = __SOURCE_DIRECTORY__ @@ "../content" +let output = __SOURCE_DIRECTORY__ @@ "../../out/docs" +let files = __SOURCE_DIRECTORY__ @@ "../files" +let templates = __SOURCE_DIRECTORY__ @@ "templates" +let formatting = __SOURCE_DIRECTORY__ @@ "../../packages/FSharp.Formatting.2.3.5-beta/" +let docTemplate = formatting @@ "templates/docpage.cshtml" + +// Where to look for *.csproj templates (in this order) +let layoutRoots = + [ templates; formatting @@ "templates" + formatting @@ "templates/reference" ] + +// Copy static files and CSS + JS from F# Formatting +let copyFiles () = + CopyRecursive files output true |> Log "Copying file: " + ensureDirectory (output @@ "content") + CopyRecursive (formatting @@ "styles") (output @@ "content") true + |> Log "Copying styles and scripts: " + +// Build API reference from XML comments +let buildReference () = + CleanDir (output @@ "reference") + for lib in referenceBinaries do + MetadataFormat.Generate + ( bin @@ lib, output @@ "reference", layoutRoots, + parameters = ("root", root)::info ) + +// Build documentation from `fsx` and `md` files in `docs/content` +let buildDocumentation () = + let subdirs = Directory.EnumerateDirectories(content, "*", SearchOption.AllDirectories) + for dir in Seq.append [content] subdirs do + let sub = if dir.Length > content.Length then dir.Substring(content.Length + 1) else "." + Literate.ProcessDirectory + ( dir, docTemplate, output @@ sub, replacements = ("root", root)::info, + layoutRoots = layoutRoots ) + +// Generate +copyFiles() +buildDocumentation() +//buildReference() diff --git a/docs/tools/packages.config b/docs/tools/packages.config new file mode 100644 index 00000000..4bb84922 --- /dev/null +++ b/docs/tools/packages.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/docs/tools/templates/template.cshtml b/docs/tools/templates/template.cshtml new file mode 100644 index 00000000..4b594ddb --- /dev/null +++ b/docs/tools/templates/template.cshtml @@ -0,0 +1,61 @@ + + + + + @Title + + + + + + + + + + + + + + + +
+
+ +

Math.NET Numerics Documenation

+
+
+
+
+ @RenderBody() +
+
+ +
+
+
+ +