Monotone cubic interpolationString Interpolation / Word Matching with XML in C#A banded interpolator, for any type and any interpolation methodCubic “bezier” curve of grade nConverting from binary to unaryOptimizing bilinear interpolationNamed string interpolationMultiplayer Peer-To-Peer position interpolationLagrange Interpolation over quadrilateral points
Can I rely on these GitHub repository files?
Can a Gentile theist be saved?
Female=gender counterpart?
How to deal with or prevent idle in the test team?
I2C signal and power over long range (10meter cable)
What is the term when two people sing in harmony, but they aren't singing the same notes?
Resetting two CD4017 counters simultaneously, only one resets
What will be the benefits of Brexit?
Can a controlled ghast be a leader of a pack of ghouls?
Have I saved too much for retirement so far?
Giant Toughroad SLR 2 for 200 miles in two days, will it make it?
Bob has never been a M before
Is there any significance to the Valyrian Stone vault door of Qarth?
Visiting the UK as unmarried couple
How do ultrasonic sensors differentiate between transmitted and received signals?
Can a malicious addon access internet history and such in chrome/firefox?
How to check participants in at events?
Why are on-board computers allowed to change controls without notifying the pilots?
What to do when my ideas aren't chosen, when I strongly disagree with the chosen solution?
Did US corporations pay demonstrators in the German demonstrations against article 13?
Is a naturally all "male" species possible?
What does the "3am" section means in manpages?
Lifted its hind leg on or lifted its hind leg towards?
word describing multiple paths to the same abstract outcome
Monotone cubic interpolation
String Interpolation / Word Matching with XML in C#A banded interpolator, for any type and any interpolation methodCubic “bezier” curve of grade nConverting from binary to unaryOptimizing bilinear interpolationNamed string interpolationMultiplayer Peer-To-Peer position interpolationLagrange Interpolation over quadrilateral points
$begingroup$
http://en.wikipedia.org/wiki/Monotone_cubic_interpolation
We have implemented it using the formula from Wikipedia :
public class MonotoneCubicSplineInterpolation
public static double[] Calc(double[] xs, double[] ys, double[] x_interp)
var length = xs.Length;
// Deal with length issues
if (length != ys.Length)
IPDevLoggerWrapper.Error("Need an equal count of xs and ys");
throw new Exception("Need an equal count of xs and ys");
if (length == 0)
return null;
if (length == 1)
return new double[] ys[0];
// Get consecutive differences and slopes
var delta = new double[length - 1];
var m = new double[length];
for (int i = 0; i < length - 1; i++)
delta[i] = (ys[i + 1] - ys[i]) / (xs[i + 1] - xs[i]);
if (i > 0)
m[i] = (delta[i - 1] + delta[i]) / 2;
var toFix = new List<int>();
for (int i = 1; i < length - 1; i++)
(delta[i] < 0 && delta[i - 1] > 0))
toFix.Add(i);
foreach (var val in toFix)
m[val] = 0;
m[0] = delta[0];
m[length - 1] = delta[length - 2];
toFix.Clear();
for (int i = 0; i < length - 1; i++)
if (delta[i] == 0)
toFix.Add(i);
foreach (var val in toFix)
m[val] = 0;
m[val + 1] = 0;
var alpha = new double[length - 1];
var beta = new double[length - 1];
var dist = new double[length - 1];
var tau = new double[length - 1];
for (int i = 0; i < length - 1; i++)
alpha[i] = m[i] / delta[i];
beta[i] = m[i + 1] / delta[i];
dist[i] = Math.Pow(alpha[i], 2) + Math.Pow(beta[i], 2);
tau[i] = 3/Math.Sqrt(dist[i]);
toFix.Clear();
for (int i = 0; i < length - 1; i++)
if (dist[i] > 9)
toFix.Add(i);
foreach (var val in toFix)
m[val] = tau[val] * alpha[val] * delta[val];
m[val + 1] = tau[val] * beta[val] * delta[val];
var y_interp = new double[x_interp.Length];
int ind = 0;
foreach (var x in x_interp)
int i;
for (i = xs.Length - 2; i >= 0; --i)
if (xs[i] <= x)
break;
var h = xs[i + 1] - xs[i];
var t = (x - xs[i])/h;
var t2 = Math.Pow(t, 2);
var t3 = Math.Pow(t, 3);
var h00 = 2*t3 - 3*t2 + 1;
var h10 = t3 - 2*t2 + t;
var h01 = -2*t3 + 3*t2;
var h11 = t3 - t2;
y_interp[ind++] = h00*ys[i] + h10*h*m[i] + h01*ys[i + 1] + h11*h*m[i + 1];
continue;
return y_interp;
Please comment about style, correctness and complexity.
c# algorithm
$endgroup$
add a comment |
$begingroup$
http://en.wikipedia.org/wiki/Monotone_cubic_interpolation
We have implemented it using the formula from Wikipedia :
public class MonotoneCubicSplineInterpolation
public static double[] Calc(double[] xs, double[] ys, double[] x_interp)
var length = xs.Length;
// Deal with length issues
if (length != ys.Length)
IPDevLoggerWrapper.Error("Need an equal count of xs and ys");
throw new Exception("Need an equal count of xs and ys");
if (length == 0)
return null;
if (length == 1)
return new double[] ys[0];
// Get consecutive differences and slopes
var delta = new double[length - 1];
var m = new double[length];
for (int i = 0; i < length - 1; i++)
delta[i] = (ys[i + 1] - ys[i]) / (xs[i + 1] - xs[i]);
if (i > 0)
m[i] = (delta[i - 1] + delta[i]) / 2;
var toFix = new List<int>();
for (int i = 1; i < length - 1; i++)
(delta[i] < 0 && delta[i - 1] > 0))
toFix.Add(i);
foreach (var val in toFix)
m[val] = 0;
m[0] = delta[0];
m[length - 1] = delta[length - 2];
toFix.Clear();
for (int i = 0; i < length - 1; i++)
if (delta[i] == 0)
toFix.Add(i);
foreach (var val in toFix)
m[val] = 0;
m[val + 1] = 0;
var alpha = new double[length - 1];
var beta = new double[length - 1];
var dist = new double[length - 1];
var tau = new double[length - 1];
for (int i = 0; i < length - 1; i++)
alpha[i] = m[i] / delta[i];
beta[i] = m[i + 1] / delta[i];
dist[i] = Math.Pow(alpha[i], 2) + Math.Pow(beta[i], 2);
tau[i] = 3/Math.Sqrt(dist[i]);
toFix.Clear();
for (int i = 0; i < length - 1; i++)
if (dist[i] > 9)
toFix.Add(i);
foreach (var val in toFix)
m[val] = tau[val] * alpha[val] * delta[val];
m[val + 1] = tau[val] * beta[val] * delta[val];
var y_interp = new double[x_interp.Length];
int ind = 0;
foreach (var x in x_interp)
int i;
for (i = xs.Length - 2; i >= 0; --i)
if (xs[i] <= x)
break;
var h = xs[i + 1] - xs[i];
var t = (x - xs[i])/h;
var t2 = Math.Pow(t, 2);
var t3 = Math.Pow(t, 3);
var h00 = 2*t3 - 3*t2 + 1;
var h10 = t3 - 2*t2 + t;
var h01 = -2*t3 + 3*t2;
var h11 = t3 - t2;
y_interp[ind++] = h00*ys[i] + h10*h*m[i] + h01*ys[i + 1] + h11*h*m[i + 1];
continue;
return y_interp;
Please comment about style, correctness and complexity.
c# algorithm
$endgroup$
$begingroup$
Regarding correctness: Where are your unit tests? This is trivial to write unit tests for.
$endgroup$
– Daniel Mann
Dec 14 '14 at 18:19
$begingroup$
@DanielMann it is tested the results are ok. i'm talking in a more general way.
$endgroup$
– Gilad
Dec 14 '14 at 21:11
add a comment |
$begingroup$
http://en.wikipedia.org/wiki/Monotone_cubic_interpolation
We have implemented it using the formula from Wikipedia :
public class MonotoneCubicSplineInterpolation
public static double[] Calc(double[] xs, double[] ys, double[] x_interp)
var length = xs.Length;
// Deal with length issues
if (length != ys.Length)
IPDevLoggerWrapper.Error("Need an equal count of xs and ys");
throw new Exception("Need an equal count of xs and ys");
if (length == 0)
return null;
if (length == 1)
return new double[] ys[0];
// Get consecutive differences and slopes
var delta = new double[length - 1];
var m = new double[length];
for (int i = 0; i < length - 1; i++)
delta[i] = (ys[i + 1] - ys[i]) / (xs[i + 1] - xs[i]);
if (i > 0)
m[i] = (delta[i - 1] + delta[i]) / 2;
var toFix = new List<int>();
for (int i = 1; i < length - 1; i++)
(delta[i] < 0 && delta[i - 1] > 0))
toFix.Add(i);
foreach (var val in toFix)
m[val] = 0;
m[0] = delta[0];
m[length - 1] = delta[length - 2];
toFix.Clear();
for (int i = 0; i < length - 1; i++)
if (delta[i] == 0)
toFix.Add(i);
foreach (var val in toFix)
m[val] = 0;
m[val + 1] = 0;
var alpha = new double[length - 1];
var beta = new double[length - 1];
var dist = new double[length - 1];
var tau = new double[length - 1];
for (int i = 0; i < length - 1; i++)
alpha[i] = m[i] / delta[i];
beta[i] = m[i + 1] / delta[i];
dist[i] = Math.Pow(alpha[i], 2) + Math.Pow(beta[i], 2);
tau[i] = 3/Math.Sqrt(dist[i]);
toFix.Clear();
for (int i = 0; i < length - 1; i++)
if (dist[i] > 9)
toFix.Add(i);
foreach (var val in toFix)
m[val] = tau[val] * alpha[val] * delta[val];
m[val + 1] = tau[val] * beta[val] * delta[val];
var y_interp = new double[x_interp.Length];
int ind = 0;
foreach (var x in x_interp)
int i;
for (i = xs.Length - 2; i >= 0; --i)
if (xs[i] <= x)
break;
var h = xs[i + 1] - xs[i];
var t = (x - xs[i])/h;
var t2 = Math.Pow(t, 2);
var t3 = Math.Pow(t, 3);
var h00 = 2*t3 - 3*t2 + 1;
var h10 = t3 - 2*t2 + t;
var h01 = -2*t3 + 3*t2;
var h11 = t3 - t2;
y_interp[ind++] = h00*ys[i] + h10*h*m[i] + h01*ys[i + 1] + h11*h*m[i + 1];
continue;
return y_interp;
Please comment about style, correctness and complexity.
c# algorithm
$endgroup$
http://en.wikipedia.org/wiki/Monotone_cubic_interpolation
We have implemented it using the formula from Wikipedia :
public class MonotoneCubicSplineInterpolation
public static double[] Calc(double[] xs, double[] ys, double[] x_interp)
var length = xs.Length;
// Deal with length issues
if (length != ys.Length)
IPDevLoggerWrapper.Error("Need an equal count of xs and ys");
throw new Exception("Need an equal count of xs and ys");
if (length == 0)
return null;
if (length == 1)
return new double[] ys[0];
// Get consecutive differences and slopes
var delta = new double[length - 1];
var m = new double[length];
for (int i = 0; i < length - 1; i++)
delta[i] = (ys[i + 1] - ys[i]) / (xs[i + 1] - xs[i]);
if (i > 0)
m[i] = (delta[i - 1] + delta[i]) / 2;
var toFix = new List<int>();
for (int i = 1; i < length - 1; i++)
(delta[i] < 0 && delta[i - 1] > 0))
toFix.Add(i);
foreach (var val in toFix)
m[val] = 0;
m[0] = delta[0];
m[length - 1] = delta[length - 2];
toFix.Clear();
for (int i = 0; i < length - 1; i++)
if (delta[i] == 0)
toFix.Add(i);
foreach (var val in toFix)
m[val] = 0;
m[val + 1] = 0;
var alpha = new double[length - 1];
var beta = new double[length - 1];
var dist = new double[length - 1];
var tau = new double[length - 1];
for (int i = 0; i < length - 1; i++)
alpha[i] = m[i] / delta[i];
beta[i] = m[i + 1] / delta[i];
dist[i] = Math.Pow(alpha[i], 2) + Math.Pow(beta[i], 2);
tau[i] = 3/Math.Sqrt(dist[i]);
toFix.Clear();
for (int i = 0; i < length - 1; i++)
if (dist[i] > 9)
toFix.Add(i);
foreach (var val in toFix)
m[val] = tau[val] * alpha[val] * delta[val];
m[val + 1] = tau[val] * beta[val] * delta[val];
var y_interp = new double[x_interp.Length];
int ind = 0;
foreach (var x in x_interp)
int i;
for (i = xs.Length - 2; i >= 0; --i)
if (xs[i] <= x)
break;
var h = xs[i + 1] - xs[i];
var t = (x - xs[i])/h;
var t2 = Math.Pow(t, 2);
var t3 = Math.Pow(t, 3);
var h00 = 2*t3 - 3*t2 + 1;
var h10 = t3 - 2*t2 + t;
var h01 = -2*t3 + 3*t2;
var h11 = t3 - t2;
y_interp[ind++] = h00*ys[i] + h10*h*m[i] + h01*ys[i + 1] + h11*h*m[i + 1];
continue;
return y_interp;
Please comment about style, correctness and complexity.
c# algorithm
c# algorithm
asked Dec 14 '14 at 17:53
GiladGilad
1,38831632
1,38831632
$begingroup$
Regarding correctness: Where are your unit tests? This is trivial to write unit tests for.
$endgroup$
– Daniel Mann
Dec 14 '14 at 18:19
$begingroup$
@DanielMann it is tested the results are ok. i'm talking in a more general way.
$endgroup$
– Gilad
Dec 14 '14 at 21:11
add a comment |
$begingroup$
Regarding correctness: Where are your unit tests? This is trivial to write unit tests for.
$endgroup$
– Daniel Mann
Dec 14 '14 at 18:19
$begingroup$
@DanielMann it is tested the results are ok. i'm talking in a more general way.
$endgroup$
– Gilad
Dec 14 '14 at 21:11
$begingroup$
Regarding correctness: Where are your unit tests? This is trivial to write unit tests for.
$endgroup$
– Daniel Mann
Dec 14 '14 at 18:19
$begingroup$
Regarding correctness: Where are your unit tests? This is trivial to write unit tests for.
$endgroup$
– Daniel Mann
Dec 14 '14 at 18:19
$begingroup$
@DanielMann it is tested the results are ok. i'm talking in a more general way.
$endgroup$
– Gilad
Dec 14 '14 at 21:11
$begingroup$
@DanielMann it is tested the results are ok. i'm talking in a more general way.
$endgroup$
– Gilad
Dec 14 '14 at 21:11
add a comment |
2 Answers
2
active
oldest
votes
$begingroup$
Don't throw Exception
throw new Exception("Need an equal count of xs and ys");
It forces client code to catch any subclass of Exception
. In this case I would throw an ArgumentException
.
The continue
at the end of the last loop is redundant.
Here you're using double.Equals
if (delta[i] == 0)
From MSDN
The
Equals
method should be used with caution, because two apparently
equivalent values can be unequal due to the differing precision of the
two values.
That link covers two techniques for dealing with this.
As far as I can tell, toFix
can be removed. For example,
var toFix = new List<int>();
for (int i = 1; i < length - 1; i++)
foreach (var val in toFix)
m[val] = 0;
Can be rewritten as
for (int i = 1; i < length - 1; i++)
$endgroup$
add a comment |
$begingroup$
I've just had to write this algorithm for some work i have been trying to complete. Couple with the wiki page on monotone cubic interpolation and your example i have optimised (slightly) and re-written the example. This can be done O(n) but chosen to use two for loops and the interpolation loop - can be optimised further.
public class MonotoneCubicSpline
private readonly double[] _x;
private readonly double[] _y;
private readonly int _n;
private readonly double[] _m;
public MonotoneCubicSpline(IList<Point> points)
_x = points.OrderBy(p => p.X).Select(p => p.X).ToArray();
_y = points.OrderBy(p => p.X).Select(p => p.Y).ToArray();
_n = points.Count;
_m = new double[_n];
var delta = new double[_n - 1];
for (var k = 0; k < _n - 1; k++)
// 1. Find the slope of the section.
delta[k] = (_y[k + 1] - _y[k]) / (_x[k + 1] - _x[k]);
// 2. Obtain an initial estimate of the control point slope.
if (k == 0)
_m[k] = delta[k];
else
(delta[k] < 0 && delta[k - 1] > 0))
_m[k] = 0;
else
_m[k] = (delta[k - 1] + delta[k]) / 2;
_m[0] = delta[0];
_m[_n - 1] = delta[_n - 2];
// Improve control point slope.
for (var k = 0; k < _n -1; k++)
public double Interpolate(double x)
if (x >= _x[_n - 1])
return (float) _y[_n - 1];
if (x <= _x[0])
return (float) _y[0];
var i = 0;
for (i = _x.Length - 1; i >= 0; i--)
if (_x[i] <= x)
break;
var h = _x[i + 1] - _x[i];
var t = (x - _x[i]) / h;
var t2 = Math.Pow(t, 2);
var t3 = Math.Pow(t, 3);
var h00 = 2 * t3 - 3 * t2 + 1;
var h10 = t3 - 2 * t2 + t;
var h01 = -2 * t3 + 3 * t2;
var h11 = t3 - t2;
var v = h00 * _y[i] + h10 * h * _m[i] + h01 * _y[i + 1] + h11 * h * _m[i + 1];
return v;
New contributor
$endgroup$
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f73622%2fmonotone-cubic-interpolation%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
Don't throw Exception
throw new Exception("Need an equal count of xs and ys");
It forces client code to catch any subclass of Exception
. In this case I would throw an ArgumentException
.
The continue
at the end of the last loop is redundant.
Here you're using double.Equals
if (delta[i] == 0)
From MSDN
The
Equals
method should be used with caution, because two apparently
equivalent values can be unequal due to the differing precision of the
two values.
That link covers two techniques for dealing with this.
As far as I can tell, toFix
can be removed. For example,
var toFix = new List<int>();
for (int i = 1; i < length - 1; i++)
foreach (var val in toFix)
m[val] = 0;
Can be rewritten as
for (int i = 1; i < length - 1; i++)
$endgroup$
add a comment |
$begingroup$
Don't throw Exception
throw new Exception("Need an equal count of xs and ys");
It forces client code to catch any subclass of Exception
. In this case I would throw an ArgumentException
.
The continue
at the end of the last loop is redundant.
Here you're using double.Equals
if (delta[i] == 0)
From MSDN
The
Equals
method should be used with caution, because two apparently
equivalent values can be unequal due to the differing precision of the
two values.
That link covers two techniques for dealing with this.
As far as I can tell, toFix
can be removed. For example,
var toFix = new List<int>();
for (int i = 1; i < length - 1; i++)
foreach (var val in toFix)
m[val] = 0;
Can be rewritten as
for (int i = 1; i < length - 1; i++)
$endgroup$
add a comment |
$begingroup$
Don't throw Exception
throw new Exception("Need an equal count of xs and ys");
It forces client code to catch any subclass of Exception
. In this case I would throw an ArgumentException
.
The continue
at the end of the last loop is redundant.
Here you're using double.Equals
if (delta[i] == 0)
From MSDN
The
Equals
method should be used with caution, because two apparently
equivalent values can be unequal due to the differing precision of the
two values.
That link covers two techniques for dealing with this.
As far as I can tell, toFix
can be removed. For example,
var toFix = new List<int>();
for (int i = 1; i < length - 1; i++)
foreach (var val in toFix)
m[val] = 0;
Can be rewritten as
for (int i = 1; i < length - 1; i++)
$endgroup$
Don't throw Exception
throw new Exception("Need an equal count of xs and ys");
It forces client code to catch any subclass of Exception
. In this case I would throw an ArgumentException
.
The continue
at the end of the last loop is redundant.
Here you're using double.Equals
if (delta[i] == 0)
From MSDN
The
Equals
method should be used with caution, because two apparently
equivalent values can be unequal due to the differing precision of the
two values.
That link covers two techniques for dealing with this.
As far as I can tell, toFix
can be removed. For example,
var toFix = new List<int>();
for (int i = 1; i < length - 1; i++)
foreach (var val in toFix)
m[val] = 0;
Can be rewritten as
for (int i = 1; i < length - 1; i++)
answered Dec 14 '14 at 22:13
mjolkamjolka
15.6k22272
15.6k22272
add a comment |
add a comment |
$begingroup$
I've just had to write this algorithm for some work i have been trying to complete. Couple with the wiki page on monotone cubic interpolation and your example i have optimised (slightly) and re-written the example. This can be done O(n) but chosen to use two for loops and the interpolation loop - can be optimised further.
public class MonotoneCubicSpline
private readonly double[] _x;
private readonly double[] _y;
private readonly int _n;
private readonly double[] _m;
public MonotoneCubicSpline(IList<Point> points)
_x = points.OrderBy(p => p.X).Select(p => p.X).ToArray();
_y = points.OrderBy(p => p.X).Select(p => p.Y).ToArray();
_n = points.Count;
_m = new double[_n];
var delta = new double[_n - 1];
for (var k = 0; k < _n - 1; k++)
// 1. Find the slope of the section.
delta[k] = (_y[k + 1] - _y[k]) / (_x[k + 1] - _x[k]);
// 2. Obtain an initial estimate of the control point slope.
if (k == 0)
_m[k] = delta[k];
else
(delta[k] < 0 && delta[k - 1] > 0))
_m[k] = 0;
else
_m[k] = (delta[k - 1] + delta[k]) / 2;
_m[0] = delta[0];
_m[_n - 1] = delta[_n - 2];
// Improve control point slope.
for (var k = 0; k < _n -1; k++)
public double Interpolate(double x)
if (x >= _x[_n - 1])
return (float) _y[_n - 1];
if (x <= _x[0])
return (float) _y[0];
var i = 0;
for (i = _x.Length - 1; i >= 0; i--)
if (_x[i] <= x)
break;
var h = _x[i + 1] - _x[i];
var t = (x - _x[i]) / h;
var t2 = Math.Pow(t, 2);
var t3 = Math.Pow(t, 3);
var h00 = 2 * t3 - 3 * t2 + 1;
var h10 = t3 - 2 * t2 + t;
var h01 = -2 * t3 + 3 * t2;
var h11 = t3 - t2;
var v = h00 * _y[i] + h10 * h * _m[i] + h01 * _y[i + 1] + h11 * h * _m[i + 1];
return v;
New contributor
$endgroup$
add a comment |
$begingroup$
I've just had to write this algorithm for some work i have been trying to complete. Couple with the wiki page on monotone cubic interpolation and your example i have optimised (slightly) and re-written the example. This can be done O(n) but chosen to use two for loops and the interpolation loop - can be optimised further.
public class MonotoneCubicSpline
private readonly double[] _x;
private readonly double[] _y;
private readonly int _n;
private readonly double[] _m;
public MonotoneCubicSpline(IList<Point> points)
_x = points.OrderBy(p => p.X).Select(p => p.X).ToArray();
_y = points.OrderBy(p => p.X).Select(p => p.Y).ToArray();
_n = points.Count;
_m = new double[_n];
var delta = new double[_n - 1];
for (var k = 0; k < _n - 1; k++)
// 1. Find the slope of the section.
delta[k] = (_y[k + 1] - _y[k]) / (_x[k + 1] - _x[k]);
// 2. Obtain an initial estimate of the control point slope.
if (k == 0)
_m[k] = delta[k];
else
(delta[k] < 0 && delta[k - 1] > 0))
_m[k] = 0;
else
_m[k] = (delta[k - 1] + delta[k]) / 2;
_m[0] = delta[0];
_m[_n - 1] = delta[_n - 2];
// Improve control point slope.
for (var k = 0; k < _n -1; k++)
public double Interpolate(double x)
if (x >= _x[_n - 1])
return (float) _y[_n - 1];
if (x <= _x[0])
return (float) _y[0];
var i = 0;
for (i = _x.Length - 1; i >= 0; i--)
if (_x[i] <= x)
break;
var h = _x[i + 1] - _x[i];
var t = (x - _x[i]) / h;
var t2 = Math.Pow(t, 2);
var t3 = Math.Pow(t, 3);
var h00 = 2 * t3 - 3 * t2 + 1;
var h10 = t3 - 2 * t2 + t;
var h01 = -2 * t3 + 3 * t2;
var h11 = t3 - t2;
var v = h00 * _y[i] + h10 * h * _m[i] + h01 * _y[i + 1] + h11 * h * _m[i + 1];
return v;
New contributor
$endgroup$
add a comment |
$begingroup$
I've just had to write this algorithm for some work i have been trying to complete. Couple with the wiki page on monotone cubic interpolation and your example i have optimised (slightly) and re-written the example. This can be done O(n) but chosen to use two for loops and the interpolation loop - can be optimised further.
public class MonotoneCubicSpline
private readonly double[] _x;
private readonly double[] _y;
private readonly int _n;
private readonly double[] _m;
public MonotoneCubicSpline(IList<Point> points)
_x = points.OrderBy(p => p.X).Select(p => p.X).ToArray();
_y = points.OrderBy(p => p.X).Select(p => p.Y).ToArray();
_n = points.Count;
_m = new double[_n];
var delta = new double[_n - 1];
for (var k = 0; k < _n - 1; k++)
// 1. Find the slope of the section.
delta[k] = (_y[k + 1] - _y[k]) / (_x[k + 1] - _x[k]);
// 2. Obtain an initial estimate of the control point slope.
if (k == 0)
_m[k] = delta[k];
else
(delta[k] < 0 && delta[k - 1] > 0))
_m[k] = 0;
else
_m[k] = (delta[k - 1] + delta[k]) / 2;
_m[0] = delta[0];
_m[_n - 1] = delta[_n - 2];
// Improve control point slope.
for (var k = 0; k < _n -1; k++)
public double Interpolate(double x)
if (x >= _x[_n - 1])
return (float) _y[_n - 1];
if (x <= _x[0])
return (float) _y[0];
var i = 0;
for (i = _x.Length - 1; i >= 0; i--)
if (_x[i] <= x)
break;
var h = _x[i + 1] - _x[i];
var t = (x - _x[i]) / h;
var t2 = Math.Pow(t, 2);
var t3 = Math.Pow(t, 3);
var h00 = 2 * t3 - 3 * t2 + 1;
var h10 = t3 - 2 * t2 + t;
var h01 = -2 * t3 + 3 * t2;
var h11 = t3 - t2;
var v = h00 * _y[i] + h10 * h * _m[i] + h01 * _y[i + 1] + h11 * h * _m[i + 1];
return v;
New contributor
$endgroup$
I've just had to write this algorithm for some work i have been trying to complete. Couple with the wiki page on monotone cubic interpolation and your example i have optimised (slightly) and re-written the example. This can be done O(n) but chosen to use two for loops and the interpolation loop - can be optimised further.
public class MonotoneCubicSpline
private readonly double[] _x;
private readonly double[] _y;
private readonly int _n;
private readonly double[] _m;
public MonotoneCubicSpline(IList<Point> points)
_x = points.OrderBy(p => p.X).Select(p => p.X).ToArray();
_y = points.OrderBy(p => p.X).Select(p => p.Y).ToArray();
_n = points.Count;
_m = new double[_n];
var delta = new double[_n - 1];
for (var k = 0; k < _n - 1; k++)
// 1. Find the slope of the section.
delta[k] = (_y[k + 1] - _y[k]) / (_x[k + 1] - _x[k]);
// 2. Obtain an initial estimate of the control point slope.
if (k == 0)
_m[k] = delta[k];
else
(delta[k] < 0 && delta[k - 1] > 0))
_m[k] = 0;
else
_m[k] = (delta[k - 1] + delta[k]) / 2;
_m[0] = delta[0];
_m[_n - 1] = delta[_n - 2];
// Improve control point slope.
for (var k = 0; k < _n -1; k++)
public double Interpolate(double x)
if (x >= _x[_n - 1])
return (float) _y[_n - 1];
if (x <= _x[0])
return (float) _y[0];
var i = 0;
for (i = _x.Length - 1; i >= 0; i--)
if (_x[i] <= x)
break;
var h = _x[i + 1] - _x[i];
var t = (x - _x[i]) / h;
var t2 = Math.Pow(t, 2);
var t3 = Math.Pow(t, 3);
var h00 = 2 * t3 - 3 * t2 + 1;
var h10 = t3 - 2 * t2 + t;
var h01 = -2 * t3 + 3 * t2;
var h11 = t3 - t2;
var v = h00 * _y[i] + h10 * h * _m[i] + h01 * _y[i + 1] + h11 * h * _m[i + 1];
return v;
New contributor
New contributor
answered 15 mins ago
Adam HAdam H
101
101
New contributor
New contributor
add a comment |
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f73622%2fmonotone-cubic-interpolation%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
$begingroup$
Regarding correctness: Where are your unit tests? This is trivial to write unit tests for.
$endgroup$
– Daniel Mann
Dec 14 '14 at 18:19
$begingroup$
@DanielMann it is tested the results are ok. i'm talking in a more general way.
$endgroup$
– Gilad
Dec 14 '14 at 21:11