diff --git a/BenchmarkDotNetCore/BenchmarkDotNetCore.csproj b/BenchmarkDotNetCore/BenchmarkDotNetCore.csproj
new file mode 100644
index 0000000..6f55e08
--- /dev/null
+++ b/BenchmarkDotNetCore/BenchmarkDotNetCore.csproj
@@ -0,0 +1,14 @@
+
+
+
+ Exe
+ netcoreapp2.0
+
+
+
+
+
+
+
+
+
diff --git a/BenchmarkDotNetCore/Program.cs b/BenchmarkDotNetCore/Program.cs
new file mode 100644
index 0000000..b74b699
--- /dev/null
+++ b/BenchmarkDotNetCore/Program.cs
@@ -0,0 +1,173 @@
+using System;
+using System.Linq;
+using System.Diagnostics;
+using FixPointCS;
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Running;
+
+namespace BenchmarkDotNetCore
+{
+ using ValueGenerator = Func;
+
+ #region Input generator
+
+ class Input
+ {
+ public enum SignMode
+ {
+ Direct,
+ Negate,
+ Random
+ }
+
+ static public ValueGenerator Uniform(double mn, double mx)
+ {
+ return (Random rnd, int count) =>
+ {
+ double[] values = new double[count];
+ for (int i = 0; i < count; i++)
+ values[i] = mn + (mx - mn) * rnd.NextDouble();
+ return values;
+ };
+ }
+
+ static public ValueGenerator Exponential(double mn, double mx, SignMode signMode = SignMode.Direct)
+ {
+ Debug.Assert(Math.Sign(mn) == Math.Sign(mx));
+ Debug.Assert(Math.Abs(mn) < Math.Abs(mx));
+
+ double ratio = Math.Log(mx / mn, 2.0);
+ return (Random rnd, int count) =>
+ {
+ double[] values = new double[count];
+ switch (signMode)
+ {
+ case SignMode.Direct:
+ for (int i = 0; i < count; i++)
+ values[i] = mn * Math.Pow(2.0, ratio * rnd.NextDouble());
+ break;
+
+ case SignMode.Negate:
+ for (int i = 0; i < count; i++)
+ values[i] = -mn * Math.Pow(2.0, ratio * rnd.NextDouble());
+ break;
+
+ case SignMode.Random:
+ for (int i = 0; i < count; i++)
+ values[i] = ((i & 2) - 1) * mn * Math.Pow(2.0, ratio * rnd.NextDouble());
+ break;
+ }
+ return values;
+ };
+ }
+ };
+
+ #endregion // Input generator
+
+
+ #region Ceil
+
+ public class CeilFP64vsDouble
+ {
+ private const int BENCHMARK_CHUNK_SIZE = 128;
+ private static readonly Random rnd = new Random(12345678);
+
+ private readonly double[] doubleArrayInputs;
+ private readonly F64[] f64ArrayInputs;
+
+ private readonly double[] doubleArrayOutputs;
+ private readonly F64[] f64ArrayOutputs;
+
+ public CeilFP64vsDouble()
+ {
+ ValueGenerator inputGenerator = Input.Uniform(-1.0, 1.0);
+
+ this.doubleArrayInputs = inputGenerator(rnd, BENCHMARK_CHUNK_SIZE);
+ this.f64ArrayInputs = this.doubleArrayInputs.Select(d => F64.FromDouble(d)).ToArray();
+
+ this.doubleArrayOutputs = new double[BENCHMARK_CHUNK_SIZE];
+ this.f64ArrayOutputs = new F64[BENCHMARK_CHUNK_SIZE];
+ }
+
+ [Benchmark]
+ public void FP64Run()
+ {
+ for (int i = 0; i < f64ArrayInputs.Length; i++)
+ {
+ this.f64ArrayOutputs[i] = this.f64ArrayInputs[i].Ceil();
+ }
+ }
+
+ [Benchmark(Baseline = true)]
+ public void DoubleRun()
+ {
+ for (int i = 0; i < doubleArrayInputs.Length; i++)
+ {
+ this.doubleArrayOutputs[i] = Math.Ceiling(this.doubleArrayInputs[i]);
+ }
+ }
+ }
+
+ #endregion // Ceil
+
+
+ #region Floor
+
+ public class FloorFP64vsDouble
+ {
+ private const int BENCHMARK_CHUNK_SIZE = 128;
+ private static readonly Random rnd = new Random(12345678);
+
+ private readonly double[] doubleArrayInputs;
+ private readonly F64[] f64ArrayInputs;
+
+ private readonly double[] doubleArrayOutputs;
+ private readonly F64[] f64ArrayOutputs;
+
+ public FloorFP64vsDouble()
+ {
+ ValueGenerator inputGenerator = Input.Uniform(-1.0, 1.0);
+
+ this.doubleArrayInputs = inputGenerator(rnd, BENCHMARK_CHUNK_SIZE);
+ this.f64ArrayInputs = this.doubleArrayInputs.Select(d => F64.FromDouble(d)).ToArray();
+
+ this.doubleArrayOutputs = new double[BENCHMARK_CHUNK_SIZE];
+ this.f64ArrayOutputs = new F64[BENCHMARK_CHUNK_SIZE];
+ }
+
+ [Benchmark]
+ public void FP64Run()
+ {
+ for (int i = 0; i < f64ArrayInputs.Length; i++)
+ {
+ this.f64ArrayOutputs[i] = this.f64ArrayInputs[i].Floor();
+ }
+ }
+
+ [Benchmark(Baseline = true)]
+ public void DoubleRun()
+ {
+ for (int i = 0; i < doubleArrayInputs.Length; i++)
+ {
+ this.doubleArrayOutputs[i] = Math.Floor(this.doubleArrayInputs[i]);
+ }
+ }
+ }
+
+ #endregion // Floor
+
+
+ public class Program
+ {
+ static void Main(string[] args)
+ {
+ var switcher = new BenchmarkSwitcher(new[] {
+ typeof(CeilFP64vsDouble),
+ typeof(FloorFP64vsDouble)
+ // If you add another benchmark, please add reference to here
+ });
+
+ switcher.Run(args);
+ }
+ }
+}
diff --git a/BenchmarkDotNetCore/readme.md b/BenchmarkDotNetCore/readme.md
new file mode 100644
index 0000000..c0c0504
--- /dev/null
+++ b/BenchmarkDotNetCore/readme.md
@@ -0,0 +1,23 @@
+# Benchmark FixPointCS with BenchmarkDotNet
+This project can be used to benchmark FixPointCS C# version with [BenchmarkDotNet](http://benchmarkdotnet.org/).
+
+## Requirements
+* [.NET Core](https://www.microsoft.com/net/download/windows)
+* BenchmarkDotNet
+* FixPointCS
+
+## Benchmark guide
+1. Make sure you have .NET Core installed (*dotnet --version*)
+2. Download the [FixPointCS](https://github.com/XMunkki/FixPointCS) to your computer
+3. Move to **BenchmarkDotNet** folder
+4. Do dotnet restore (*dotnet restore*) and wait few seconds while additional files are downloaded
+5. Run the benchmark you want (Either via *dotnet run -c Release* and select benchmark or provide benchmark as parameter, like *dotnet run -c Release 0*)
+6. Wait while benchmark runs and check out results afterwards from console/terminal or from **BenchmarkDotNet.Artifacts\results** folder
+
+## Development guide
+
+### Add additional benchmark
+You can copy and paste existing code from **Program.cs** file (e.g. *public class CeilFP64vsDouble*) to create new benchmark. You have to also add new entry to the **switcher** variable located in *static void Main(string[] args)* in case you want to run your benchmark via switcher
+
+### Add something fancy to benchmarks
+BenchmarkDotNet does provide many nice features and you can find more help related to BenchmarkDotNet from [the official documentation](http://benchmarkdotnet.org/Guides/GettingStarted.htm)
\ No newline at end of file