using System; using System.Collections; namespace MarketData.Numerical { // The column is the key, the row is the value. // For Time series elements put the date in the column and the value in the row public class Element { private double row; private double column; public Element() { } public Element(double column, double row) { this.column = column; this.row = row; } public double Row { get { return row; } set { row = value; } } public double Column { get { return column; } set { column = value; } } } public class CatmullRom { private CatmullRom() { } public static bool PerformSpline(Element[] sourcePairs, Element[] destPairs) { double a0, a1, a2, a3; double dx, dx1, dx2; double dy, dy1, dy2; double endPointOne; double endPointTwo; double resamplingPos; double xPoint; int clampOne, clampTwo; int direction; int destSize = destPairs.Length; int sourceSize = sourcePairs.Length; int inputIndex, index; a0 = a1 = a2 = a3 = endPointOne = 0; if (sourceSize < 2 || destSize < 1) return false; if (((Element)sourcePairs[0]).Column < ((Element)sourcePairs[1]).Column) { if (((Element)destPairs[0]).Column < ((Element)sourcePairs[0]).Column || ((Element)destPairs[destSize - 1]).Column > ((Element)sourcePairs[sourceSize - 1]).Column) direction = 0; else direction = 1; } else { if (((Element)destPairs[0]).Column > ((Element)sourcePairs[0]).Column || ((Element)destPairs[destSize - 1]).Column < ((Element)sourcePairs[sourceSize - 1]).Column) direction = 0; else direction = -1; } if (0 == direction) return false; if (1 == direction) endPointTwo = ((Element)destPairs[0]).Column - 1; else endPointTwo = ((Element)destPairs[0]).Column + 1; for (index = 0; index < destSize; index++) { resamplingPos = ((Element)destPairs[index]).Column; if ((1 == direction && resamplingPos > endPointTwo) || (-1 == direction && resamplingPos < endPointTwo)) { for (inputIndex = 0; inputIndex < sourceSize && resamplingPos > ((Element)sourcePairs[inputIndex]).Column; inputIndex++) ; if (resamplingPos < ((Element)sourcePairs[inputIndex]).Column) inputIndex--; if (inputIndex < 0) inputIndex = 0; else if (inputIndex == sourceSize-1) inputIndex--; endPointOne = ((Element)sourcePairs[inputIndex]).Column; endPointTwo = ((Element)sourcePairs[inputIndex + 1]).Column; clampOne = Math.Max(inputIndex - 1, 0); clampTwo = Math.Min(inputIndex + 2, sourceSize - 1); double clampOneValue = ((Element)sourcePairs[clampOne]).Column; double clampTwoValue = ((Element)sourcePairs[clampTwo]).Column; dx = 1.0 / ((endPointTwo - endPointOne)==0?1:(endPointTwo-endPointOne)); dx1 = 1.0 / ((endPointTwo - clampOneValue) == 0 ? 1 : (endPointTwo - clampOneValue)); dx2 = 1.0 / (clampTwoValue-endPointOne == 0 ? 1 : (clampTwoValue - endPointOne)); dy = (((Element)sourcePairs[inputIndex + 1]).Row - ((Element)sourcePairs[inputIndex]).Row) * dx; dy1 = (((Element)sourcePairs[inputIndex + 1]).Row - ((Element)sourcePairs[clampOne]).Row) * dx1; dy2 = (((Element)sourcePairs[clampTwo]).Row - ((Element)sourcePairs[inputIndex]).Row) * dx2; a0 = ((Element)sourcePairs[inputIndex]).Row; a1 = dy1; a2 = dx * (3 * dy - 2 * dy1 - dy2); a3 = dx * dx * (-2 * dy + dy1 + dy2); } xPoint = resamplingPos - endPointOne; ((Element)destPairs[index]).Row = ((a3 * xPoint + a2) * xPoint + a1) * xPoint + a0; } return true; } public static Element[] CreateSplineSourceElements(double[] columns, double[] rows) { Element[] elements = new Element[columns.Length]; if (columns.Length != rows.Length) return null; for (int index = 0; index < columns.Length; index++) { elements[index] = new Element(columns[index], rows[index]); } return elements; } } } // namespace