SplineFunction.h
Go to the documentation of this file.
1 #ifndef _SplineFunction_Spline_h_
2 #define _SplineFunction_Spline_h_
3 
4 #include <cmath>
5 #include <vector>
6 #include <algorithm>
7 #include <limits>
8 #include <iostream>
9 #include <utl/AugerException.h>
10 
11 namespace Spline {
12 
13  typedef unsigned char dim_t;
14 
15  template <dim_t ADimension, typename AKnotVector, typename ABasisFunction>
16  class Function {
17  public:
18 
19  typedef std::vector<ABasisFunction> BasisVector;
20 
22  {
23  for (dim_t idim = 0; idim < ADimension; ++idim)
24  fCacheX[idim] = std::numeric_limits<double>::quiet_NaN();
25  }
26 
27  void
28  Configure(const dim_t idim, const AKnotVector& knots)
29  {
30  fKnotVectors[idim] = knots;
31 
32  const size_t size = fKnotVectors[idim].GetSize();
33  fBasisVectors[idim].resize(size+2);
34  for (size_t k = 0; k < size+2; ++k)
35  fBasisVectors[idim][k] = ABasisFunction(&fKnotVectors[idim], k);
36 
37  fStrides[0] = 0; // mark fStrides for re-computing
38  }
39 
40  double
41  operator()(const double* coefs, const double* x)
42  const
43  {
44  if (fStrides[0] == 0)
45  {
46  // fStrides need recomputing
47  fStrides[0] = 1;
48  for (dim_t idim = 0; idim < ADimension-1; ++idim)
49  fStrides[idim+1] = GetSize(idim)*fStrides[idim];
50  }
51 
52  size_t i[ADimension];
53  for (size_t idim = 0; idim < ADimension; ++idim)
54  i[idim] = fKnotVectors[idim].Locate(x[idim]);
55 
56  double result = 0;
57  for (size_t j = 0; j < (1 << 2*ADimension); ++j)
58  {
59  size_t k = 0;
60  double basis = 1.0;
61  for (dim_t idim = 0; idim < ADimension; ++idim)
62  {
63  const size_t kk = j % (1 << 2*(idim+1)) / (1 << 2*idim);
64  if (x[idim] != fCacheX[idim])
65  fCacheBasis[idim][kk] = fBasisVectors[idim][i[idim]+kk].Internal(i[idim], x[idim], 0);
66  basis *= fCacheBasis[idim][kk];
67  k += fStrides[idim]*(i[idim]+kk);
68  }
69  result += coefs[k]*basis;
70  }
71 
72  for (size_t idim = 0; idim < ADimension; ++idim)
73  fCacheX[idim] = x[idim];
74 
75  return result;
76  }
77 
78  inline
79  const AKnotVector&
80  GetKnotVector(const dim_t idim)
81  const
82  {
83  return fKnotVectors[idim];
84  }
85 
86  inline
87  const BasisVector&
88  GetBasisVector(const dim_t idim)
89  const
90  {
91  return fBasisVectors[idim];
92  }
93 
94  inline
95  size_t
96  GetSize(const dim_t idim)
97  const
98  {
99  return fBasisVectors[idim].size();
100  }
101 
102  inline
103  double
104  GetStart(const dim_t idim)
105  const
106  {
107  return fKnotVectors[idim].GetStart();
108  }
109 
110  inline
111  double
112  GetStop(const dim_t idim)
113  const
114  {
115  return fKnotVectors[idim].GetStop();
116  }
117 
118  private:
119  AKnotVector fKnotVectors[ADimension];
121  mutable size_t fStrides[ADimension];
122  mutable double fCacheX[ADimension];
123  mutable double fCacheBasis[ADimension][4];
124  };
125 
126 
127  // specialization for ADimension = 1
128  template<typename AKnotVector, typename ABasisFunction>
129  class Function<1, AKnotVector, ABasisFunction>
130  {
131  public:
132 
133  typedef std::vector<ABasisFunction> BasisVector;
134 
135  Function() {}
136 
137  Function(const AKnotVector& knots)
138  {
139  Configure(0, knots);
140  }
141 
142  void
143  Configure(const dim_t /* idim */, const AKnotVector& knots)
144  {
145  fKnotVector = knots;
146 
147  const size_t size = fKnotVector.GetSize();
148  fBasisVector.resize(size+2);
149  for (size_t k = 0; k < size+2; ++k)
150  fBasisVector[k] = ABasisFunction(&fKnotVector, k);
151  }
152 
153  inline
154  double
155  operator()(const double* coefs, const double x, const char derivative=0)
156  const
157  {
158  const size_t i = fKnotVector.Locate(x);
159  const size_t kBegin = derivative >= 0 ? i : 0;
160  const size_t kEnd = derivative >= 0 ? i+4 : GetSize();
161  double result = 0;
162  for (size_t k = kBegin; k < kEnd; ++k)
163  result += coefs[k]*fBasisVector[k].Internal(i,x,derivative);
164  return result;
165  }
166 
167  inline
168  const ABasisFunction&
169  operator[](const size_t k)
170  const
171  {
172  return fBasisVector[k];
173  }
174 
175  inline
176  const AKnotVector&
177  GetKnotVector()
178  const
179  {
180  return fKnotVector;
181  }
182 
183  inline
184  const AKnotVector&
185  GetKnotVector(const dim_t)
186  const
187  {
188  return fKnotVector;
189  }
190 
191  inline
192  const BasisVector&
193  GetBasisVector()
194  const
195  {
196  return fBasisVector;
197  }
198 
199  inline
200  const BasisVector&
201  GetBasisVector(const dim_t)
202  const
203  {
204  return fBasisVector;
205  }
206 
207  inline
208  size_t
209  GetSize()
210  const
211  {
212  return fBasisVector.size();
213  }
214 
215  inline
216  size_t
217  GetSize(const dim_t)
218  const
219  {
220  return fBasisVector.size();
221  }
222 
223  inline
224  double
225  GetStart()
226  const
227  {
228  return fKnotVector.GetStart();
229  }
230 
231  inline
232  double
233  GetStart(const dim_t)
234  const
235  {
236  return fKnotVector.GetStart();
237  }
238 
239  inline
240  double
241  GetStop()
242  const
243  {
244  return fKnotVector.GetStop();
245  }
246 
247  inline
248  double
249  GetStop(const dim_t)
250  const
251  {
252  return fKnotVector.GetStop();
253  }
254 
255  private:
256  AKnotVector fKnotVector;
258  };
259 
260 } // NS Spline
261 
262 #endif
void Configure(const dim_t, const AKnotVector &knots)
BasisVector fBasisVectors[ADimension]
double fCacheX[ADimension]
const ABasisFunction & operator[](const size_t k) const
const Data result[]
unsigned char dim_t
AKnotVector fKnotVectors[ADimension]
std::vector< ABasisFunction > BasisVector
void Configure(const dim_t idim, const AKnotVector &knots)
double operator()(const double *coefs, const double x, const char derivative=0) const
size_t fStrides[ADimension]
double fCacheBasis[ADimension][4]
double operator()(const double *coefs, const double *x) const

, generated on Tue Sep 26 2023.