~hikiko/nux/arb-srgba-shader

« back to all changes in this revision

Viewing changes to NuxCore/Math/Spline.h

  • Committer: Neil Jagdish Patel
  • Date: 2010-09-01 19:25:37 UTC
  • Revision ID: neil.patel@canonical.com-20100901192537-mfz7rm6q262pewg6
Import and build NuxCore

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifndef SPLINE_H
 
2
#define SPLINE_H
 
3
 
 
4
#include <vector>
 
5
 
 
6
NAMESPACE_BEGIN
 
7
 
 
8
double *d3_np_fs ( int n, double a[], double b[] );
 
9
double *spline_cubic_set ( int n, double t[], double y[], int ibcbeg, double ybcbeg, int ibcend, double ybcend );
 
10
double spline_cubic_val ( int n, double t[], double tval, double y[], double ypp[], double *ypval, double *yppval );
 
11
 
 
12
 
 
13
class CubicSpline
 
14
{
 
15
public:
 
16
    CubicSpline();
 
17
    CubicSpline(const CubicSpline& Other);
 
18
    CubicSpline& operator = (const CubicSpline& Other);
 
19
 
 
20
    CubicSpline(int numpoint, std::vector<double> x_array, std::vector<double> y_array, int ibcbeg = 0, double ybcbeg = 0, int ibcend = 0, double ybcend = 0);
 
21
    void Set(int numpoint, std::vector<double> x_array, std::vector<double> y_array, int ibcbeg = 0, double ybcbeg = 0, int ibcend = 0, double ybcend = 0);
 
22
 
 
23
    ~CubicSpline();
 
24
    
 
25
    //**********************************************************************
 
26
    //  double* CubicSpline::Compute ( int n, double t[], double y[], int ibcbeg, double ybcbeg, int ibcend, double ybcend )
 
27
    //  Purpose:
 
28
    //
 
29
    //    SPLINE_CUBIC_SET computes the second derivatives of a piecewise cubic spline.
 
30
    //
 
31
    //  Discussion:
 
32
    //
 
33
    //    For data interpolation, the user must call SPLINE_SET to determine
 
34
    //    the second derivative data, passing in the data to be interpolated,
 
35
    //    and the desired boundary conditions.
 
36
    //
 
37
    //    The data to be interpolated, plus the SPLINE_SET output, defines
 
38
    //    the spline.  The user may then call SPLINE_VAL to evaluate the
 
39
    //    spline at any point.
 
40
    //
 
41
    //    The cubic spline is a piecewise cubic polynomial.  The intervals
 
42
    //    are determined by the "knots" or abscissas of the data to be
 
43
    //    interpolated.  The cubic spline has continous first and second
 
44
    //    derivatives over the entire interval of interpolation.
 
45
    //
 
46
    //    For any point T in the interval T(IVAL), T(IVAL+1), the form of
 
47
    //    the spline is
 
48
    //
 
49
    //      SPL(T) = A(IVAL)
 
50
    //             + B(IVAL) * ( T - T(IVAL) )
 
51
    //             + C(IVAL) * ( T - T(IVAL) )**2
 
52
    //             + D(IVAL) * ( T - T(IVAL) )**3
 
53
    //
 
54
    //    If we assume that we know the values Y(*) and DDY(*), which represent
 
55
    //    the values and second derivatives of the spline at each knot, then
 
56
    //    the coefficients can be computed as:
 
57
    //
 
58
    //      A(IVAL) = Y(IVAL)
 
59
    //      B(IVAL) = ( Y(IVAL+1) - Y(IVAL) ) / ( T(IVAL+1) - T(IVAL) )
 
60
    //        - ( DDY(IVAL+1) + 2 * DDY(IVAL) ) * ( T(IVAL+1) - T(IVAL) ) / 6
 
61
    //      C(IVAL) = DDY(IVAL) / 2
 
62
    //      D(IVAL) = ( DDY(IVAL+1) - DDY(IVAL) ) / ( 6 * ( T(IVAL+1) - T(IVAL) ) )
 
63
    //
 
64
    //    Since the first derivative of the spline is
 
65
    //
 
66
    //      SPL'(T) =     B(IVAL)
 
67
    //              + 2 * C(IVAL) * ( T - T(IVAL) )
 
68
    //              + 3 * D(IVAL) * ( T - T(IVAL) )**2,
 
69
    //
 
70
    //    the requirement that the first derivative be continuous at interior
 
71
    //    knot I results in a total of N-2 equations, of the form:
 
72
    //
 
73
    //      B(IVAL-1) + 2 C(IVAL-1) * (T(IVAL)-T(IVAL-1)) + 3 * D(IVAL-1) * (T(IVAL) - T(IVAL-1))^2 = B(IVAL)
 
74
    //
 
75
    //    or, setting H(IVAL) = T(IVAL+1) - T(IVAL)
 
76
    //
 
77
    //      ( Y(IVAL) - Y(IVAL-1) ) / H(IVAL-1) - ( DDY(IVAL) + 2 * DDY(IVAL-1) ) * H(IVAL-1) / 6 + DDY(IVAL-1) * H(IVAL-1)
 
78
    //      + ( DDY(IVAL) - DDY(IVAL-1) ) * H(IVAL-1) / 2
 
79
    //      = ( Y(IVAL+1) - Y(IVAL) ) / H(IVAL) - ( DDY(IVAL+1) + 2 * DDY(IVAL) ) * H(IVAL) / 6
 
80
    //
 
81
    //    or
 
82
    //
 
83
    //      DDY(IVAL-1) * H(IVAL-1) + 2 * DDY(IVAL) * ( H(IVAL-1) + H(IVAL) ) + DDY(IVAL) * H(IVAL)
 
84
    //      = 6 * ( Y(IVAL+1) - Y(IVAL) ) / H(IVAL) - 6 * ( Y(IVAL) - Y(IVAL-1) ) / H(IVAL-1)
 
85
    //
 
86
    //    Boundary conditions must be applied at the first and last knots.  
 
87
    //    The resulting tridiagonal system can be solved for the DDY values.
 
88
    //
 
89
    //
 
90
    //  Parameters:
 
91
    //
 
92
    //    Input, int N, the number of data points.  N must be at least 2.
 
93
    //    In the special case where N = 2 and IBCBEG = IBCEND = 0, the
 
94
    //    spline will actually be linear.
 
95
    //
 
96
    //    Input, double T[N], the knot values, that is, the points were data is
 
97
    //    specified.  The knot values should be distinct, and increasing.
 
98
    //
 
99
    //    Input, double Y[N], the data values to be interpolated.
 
100
    //
 
101
    //    Input, int IBCBEG, left boundary condition flag:
 
102
    //      0: the cubic spline should be a quadratic over the first interval;
 
103
    //      1: the first derivative at the left endpoint should be YBCBEG;
 
104
    //      2: the second derivative at the left endpoint should be YBCBEG.
 
105
    //
 
106
    //    Input, double YBCBEG, the values to be used in the boundary
 
107
    //    conditions if IBCBEG is equal to 1 or 2.
 
108
    //
 
109
    //    Input, int IBCEND, right boundary condition flag:
 
110
    //      0: the cubic spline should be a quadratic over the last interval;
 
111
    //      1: the first derivative at the right endpoint should be YBCEND;
 
112
    //      2: the second derivative at the right endpoint should be YBCEND.
 
113
    //
 
114
    //    Input, double YBCEND, the values to be used in the boundary
 
115
    //    conditions if IBCEND is equal to 1 or 2.
 
116
    //
 
117
    //    Output, double SPLINE_CUBIC_SET[N], the second derivatives of the cubic spline.
 
118
    //
 
119
    double* Compute(int ibcbeg, double ybcbeg, int ibcend, double ybcend);
 
120
 
 
121
    //**********************************************************************
 
122
    //  double Eval ( int n, double t[], double tval, double y[], double ddy[], double *dyval, double *ddyval )
 
123
    //  Purpose:
 
124
    //
 
125
    //    SPLINE_CUBIC_VAL evaluates a piecewise cubic spline at a point.
 
126
    //
 
127
    //  Discussion:
 
128
    //
 
129
    //    SPLINE_CUBIC_SET must have already been called to define the values of YPP.
 
130
    //
 
131
    //    For any point T in the interval T(IVAL), T(IVAL+1), the form of
 
132
    //    the spline is
 
133
    //
 
134
    //      SPL(T) = A
 
135
    //             + B * ( T - T(IVAL) )
 
136
    //             + C * ( T - T(IVAL) )**2
 
137
    //             + D * ( T - T(IVAL) )**3
 
138
    //
 
139
    //    Here:
 
140
    //      A = Y(IVAL)
 
141
    //      B = ( Y(IVAL+1) - Y(IVAL) ) / ( T(IVAL+1) - T(IVAL) )
 
142
    //        - ( YPP(IVAL+1) + 2 * YPP(IVAL) ) * ( T(IVAL+1) - T(IVAL) ) / 6
 
143
    //      C = YPP(IVAL) / 2
 
144
    //      D = ( YPP(IVAL+1) - YPP(IVAL) ) / ( 6 * ( T(IVAL+1) - T(IVAL) ) )
 
145
    //
 
146
    //  Modified:
 
147
    //
 
148
    //    04 February 1999
 
149
    //
 
150
    //  Author:
 
151
    //
 
152
    //    John Burkardt
 
153
    //
 
154
    //  Parameters:
 
155
    //
 
156
    //    Input, int N, the number of knots.
 
157
    //
 
158
    //    Input, double Y[N], the data values at the knots.
 
159
    //
 
160
    //    Input, double T[N], the knot values.
 
161
    //
 
162
    //    Input, double TVAL, a point, typically between T[0] and T[N-1], at
 
163
    //    which the spline is to be evalulated.  If TVAL lies outside
 
164
    //    this range, extrapolation is used.
 
165
    //
 
166
    //    Input, double Y[N], the data values at the knots.
 
167
    //
 
168
    //    Input, double YPP[N], the second derivatives of the spline at
 
169
    //    the knots.
 
170
    //
 
171
    //    Output, double *YPVAL, the derivative of the spline at TVAL.
 
172
    //
 
173
    //    Output, double *YPPVAL, the second derivative of the spline at TVAL.
 
174
    //
 
175
    //    Output, double SPLINE_VAL, the value of the spline at TVAL.
 
176
    //
 
177
    double Eval (double tval);
 
178
 
 
179
    //**********************************************************************
 
180
    //  double* SolveTridiag ( int n, double a[], double b[] );
 
181
    //  Purpose:
 
182
    //
 
183
    //    D3_NP_FS factors and solves a D3 system.
 
184
    //
 
185
    //  Discussion:
 
186
    //
 
187
    //    The D3 storage format is used for a tridiagonal matrix.
 
188
    //    The superdiagonal is stored in entries (1,2:N), the diagonal in
 
189
    //    entries (2,1:N), and the subdiagonal in (3,1:N-1).  Thus, the
 
190
    //    original matrix is "collapsed" vertically into the array.
 
191
    //
 
192
    //    This algorithm requires that each diagonal entry be nonzero.
 
193
    //    It does not use pivoting, and so can fail on systems that
 
194
    //    are actually nonsingular.
 
195
    //
 
196
    //  Example:
 
197
    //
 
198
    //    Here is how a D3 matrix of order 5 would be stored:
 
199
    //
 
200
    //       *  A12 A23 A34 A45
 
201
    //      A11 A22 A33 A44 A55
 
202
    //      A21 A32 A43 A54  *
 
203
    //
 
204
    //  Parameters:
 
205
    //
 
206
    //    Input, int N, the order of the linear system.
 
207
    //
 
208
    //    Input/output, double A[3*N].
 
209
    //    On input, the nonzero diagonals of the linear system.
 
210
    //    On output, the data in these vectors has been overwritten
 
211
    //    by factorization information.
 
212
    //
 
213
    //    Input, double B[N], the right hand side.
 
214
    //
 
215
    //    Output, double D3_NP_FS[N], the solution of the linear system.
 
216
    //    This is NULL if there was an error because one of the diagonal
 
217
    //    entries was zero.
 
218
    //
 
219
    double* SolveTridiag ( int n, double a[], double b[] );
 
220
 
 
221
public:
 
222
    double* t;
 
223
    double* y;
 
224
    double* ddy;
 
225
 
 
226
    int ibcbeg_;
 
227
    double ybcbeg_;
 
228
    int ibcend_;
 
229
    double ybcend_;
 
230
 
 
231
    int np;  // number of points
 
232
};
 
233
 
 
234
NAMESPACE_END
 
235
 
 
236
#endif // SPLINE_H