From df8fb6a9782ad33a03515074673f3c8cbf4c4936 Mon Sep 17 00:00:00 2001 From: Candy Chiu Date: Thu, 29 May 2014 09:48:30 -0400 Subject: [PATCH] Added LogLinearSpline and TransformedInterpolation interpolators. --- src/Numerics/Interpolate.cs | 22 +++ src/Numerics/Interpolation/LogLinearSpline.cs | 141 ++++++++++++++++++ .../Interpolation/TransformedSpline.cs | 76 ++++++++++ src/Numerics/Numerics.csproj | 2 + 4 files changed, 241 insertions(+) create mode 100644 src/Numerics/Interpolation/LogLinearSpline.cs create mode 100644 src/Numerics/Interpolation/TransformedSpline.cs diff --git a/src/Numerics/Interpolate.cs b/src/Numerics/Interpolate.cs index 9049f55f..202e9f50 100644 --- a/src/Numerics/Interpolate.cs +++ b/src/Numerics/Interpolate.cs @@ -30,6 +30,7 @@ using System.Collections.Generic; using MathNet.Numerics.Interpolation; +using System; namespace MathNet.Numerics { @@ -160,6 +161,27 @@ namespace MathNet.Numerics return Interpolation.LinearSpline.Interpolate(points, values); } + /// + /// Create log linear spline interpolation based on arbitrary points. + /// + /// The sample points t. Optimized for arrays. + /// The sample point values x(t). Optimized for arrays. + /// + /// An interpolation scheme optimized for the given sample points and values, + /// which can then be used to compute interpolations and extrapolations + /// on arbitrary points. + /// + /// + /// The value pairs do not have to be sorted, but if they are not sorted ascendingly + /// and the passed x and y arguments are arrays, they will be sorted inplace and thus modified. + /// + /// If the values are passed as an array, they will be modified inplace, even it is already sorted. + /// + public static IInterpolation LogLinearSpline(IEnumerable points, IEnumerable values) + { + return new LogLinearSpline(points, values); + } + /// /// Create an piecewise natural cubic spline interpolation based on arbitrary points, /// with zero secondary derivatives at the boundaries. diff --git a/src/Numerics/Interpolation/LogLinearSpline.cs b/src/Numerics/Interpolation/LogLinearSpline.cs new file mode 100644 index 00000000..6ba0ea8e --- /dev/null +++ b/src/Numerics/Interpolation/LogLinearSpline.cs @@ -0,0 +1,141 @@ +// +// Math.NET Numerics, part of the Math.NET Project +// http://numerics.mathdotnet.com +// http://github.com/mathnet/mathnet-numerics +// http://mathnetnumerics.codeplex.com +// +// Copyright (c) 2009-2013 Math.NET +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +using MathNet.Numerics.Properties; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace MathNet.Numerics.Interpolation +{ + /// + /// Log Linear Spline Interpolation + /// + /// This algorithm supports differentiation, not integration. + public class LogLinearSpline : IInterpolation + { + /// + /// Internal Spline Interpolation + /// + private readonly LinearSpline _spline; + + /// + /// Creates a log linear interpolation based on input data + /// + /// + /// + public LogLinearSpline(IEnumerable x, IEnumerable y) + { + var xx = (x as double[]) ?? x.ToArray(); + var yy = (y as double[]) ?? y.ToArray(); + + if (xx.Length != yy.Length) + { + throw new ArgumentException(Resources.ArgumentVectorsSameLength); + } + + for (int i = 0; i < yy.Length; i++) + yy[i] = Math.Log(yy[i]); + + _spline = LinearSpline.Interpolate(xx, yy); + } + + /// + /// Gets a value indicating whether the algorithm supports differentiation (interpolated derivative). + /// + bool IInterpolation.SupportsDifferentiation + { + get { return true; } + } + + /// + /// Gets a value indicating whether the algorithm supports integration (interpolated quadrature). + /// + bool IInterpolation.SupportsIntegration + { + get { return false; } + } + + /// + /// Interpolate at point t. + /// + /// Point t to interpolate at. + /// Interpolated value x(t). + public double Interpolate(double t) + { + return Math.Exp(_spline.Interpolate(t)); + } + + /// + /// Differentiate at point t. + /// + /// Point t to interpolate at. + /// Interpolated first derivative at point t. + public double Differentiate(double t) + { + return Interpolate(t) * _spline.Differentiate(t); + } + + /// + /// Differentiate twice at point t. + /// + /// Point t to interpolate at. + /// Interpolated second derivative at point t. + public double Differentiate2(double t) + { + var linearFirstDerivative = _spline.Differentiate(t); + var linearSecondDerivative = _spline.Differentiate2(t); + + var secondDerivative = Differentiate(t) * linearFirstDerivative + + Interpolate(t) * linearSecondDerivative; + + return secondDerivative; + } + + /// + /// Indefinite integral at point t. + /// + /// Point t to integrate at. + public double Integrate(double t) + { + throw new NotImplementedException(); + } + + /// + /// Definite integral between points a and b. + /// + /// Left bound of the integration interval [a,b]. + /// Right bound of the integration interval [a,b]. + public double Integrate(double a, double b) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Numerics/Interpolation/TransformedSpline.cs b/src/Numerics/Interpolation/TransformedSpline.cs new file mode 100644 index 00000000..03147afa --- /dev/null +++ b/src/Numerics/Interpolation/TransformedSpline.cs @@ -0,0 +1,76 @@ +using MathNet.Numerics.Properties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MathNet.Numerics.Interpolation +{ + public class TransformedInterpolation : IInterpolation + { + private IInterpolation _baseInterpolation; + private Func _transformer; + + public TransformedInterpolation(IInterpolation baseInterp, Func transformer) + { + _baseInterpolation = baseInterp; + _transformer = transformer; + } + + public static TransformedInterpolation Interpolate( + Func transformer, Func transformerInverse, + IEnumerable x, IEnumerable y) + { + var xx = (x as double[]) ?? x.ToArray(); + var yy = (y as double[]) ?? y.ToArray(); + + if (xx.Length != yy.Length) + { + throw new ArgumentException(Resources.ArgumentVectorsSameLength); + } + + for (int i = 0; i < yy.Length; i++) + yy[i] = transformerInverse(yy[i]); + + var baseInterp = LinearSpline.Interpolate(xx, yy); + var interp = new TransformedInterpolation(baseInterp, transformer); + + return interp; + } + + public bool SupportsDifferentiation + { + get { return false; } + } + + public bool SupportsIntegration + { + get { return false; } + } + + public double Differentiate(double t) + { + throw new NotImplementedException(); + } + + public double Differentiate2(double t) + { + throw new NotImplementedException(); + } + + public double Integrate(double t) + { + throw new NotImplementedException(); + } + + public double Integrate(double a, double b) + { + throw new NotImplementedException(); + } + + public double Interpolate(double t) + { + return _transformer(_baseInterpolation.Interpolate(t)); + } + } +} diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj index b0600c03..5d75eb5e 100644 --- a/src/Numerics/Numerics.csproj +++ b/src/Numerics/Numerics.csproj @@ -91,8 +91,10 @@ + +