pspline 5.0.5 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -5
  3. data/README.md +44 -43
  4. data/Rakefile +6 -6
  5. data/bin/console +14 -14
  6. data/bin/setup +8 -8
  7. data/ext/pspline/basis.cpp +394 -351
  8. data/ext/pspline/example/exbspline.rb +57 -57
  9. data/ext/pspline/example/excspline.rb +57 -57
  10. data/ext/pspline/example/exdspline.rb +55 -55
  11. data/ext/pspline/example/exfspline.rb +44 -44
  12. data/ext/pspline/example/exfspline1.rb +40 -40
  13. data/ext/pspline/example/exfspline2.rb +68 -68
  14. data/ext/pspline/example/exfspline3.rb +64 -64
  15. data/ext/pspline/example/exmspline.rb +68 -68
  16. data/ext/pspline/example/expspline.rb +29 -29
  17. data/ext/pspline/example/expspline1.rb +29 -29
  18. data/ext/pspline/example/expspline2.rb +47 -47
  19. data/ext/pspline/example/exqspline.rb +31 -31
  20. data/ext/pspline/example/exqspline1.rb +31 -31
  21. data/ext/pspline/example/exqspline2.rb +50 -50
  22. data/ext/pspline/example/exqspline3.rb +51 -51
  23. data/ext/pspline/example/exqspline4.rb +35 -35
  24. data/ext/pspline/example/exrspline.rb +34 -34
  25. data/ext/pspline/example/exrspline1.rb +34 -34
  26. data/ext/pspline/example/exrspline2.rb +44 -44
  27. data/ext/pspline/example/exsspline.rb +35 -35
  28. data/ext/pspline/example/exsspline1.rb +35 -35
  29. data/ext/pspline/example/extspline.rb +54 -54
  30. data/ext/pspline/extconf.rb +7 -7
  31. data/ext/pspline/fft.cpp +27 -552
  32. data/ext/pspline/include/basis/basis.h +145 -137
  33. data/ext/pspline/include/basis/fft.h +188 -152
  34. data/ext/pspline/include/basis/fft_complex.h +215 -0
  35. data/ext/pspline/include/basis/fft_real.h +625 -0
  36. data/ext/pspline/include/basis/gabs.h +35 -0
  37. data/ext/pspline/include/basis/marray_class_ext.h +568 -0
  38. data/ext/pspline/include/basis/marray_ext.h +100 -0
  39. data/ext/pspline/include/basis/matrix_luc_ext.h +300 -0
  40. data/ext/pspline/include/basis/matrix_lud_ext.h +298 -0
  41. data/ext/pspline/include/basis/poly.h +454 -0
  42. data/ext/pspline/include/basis/poly_array.h +1030 -1568
  43. data/ext/pspline/include/basis/pspline.h +806 -642
  44. data/ext/pspline/include/basis/real.h +526 -0
  45. data/ext/pspline/include/basis/real_inline.h +442 -0
  46. data/ext/pspline/include/basis/spline.h +83 -0
  47. data/ext/pspline/include/basis/uspline.h +251 -210
  48. data/ext/pspline/include/basis/util.h +122 -656
  49. data/ext/pspline/include/bspline.h +71 -377
  50. data/ext/pspline/include/bspline_Config.h +8 -2
  51. data/ext/pspline/include/real_config.h +3 -0
  52. data/ext/pspline/pspline.cpp +1236 -1038
  53. data/ext/pspline/real.cpp +1607 -0
  54. data/ext/pspline/real_const.cpp +585 -0
  55. data/lib/pspline.rb +71 -71
  56. data/lib/pspline/version.rb +1 -1
  57. data/pspline.gemspec +25 -25
  58. metadata +17 -5
  59. data/ext/pspline/plotsub.cpp +0 -139
  60. data/ext/pspline/util.cpp +0 -483
@@ -1,642 +1,806 @@
1
- #ifndef _PSPLINE_5_H_INCLUDED_
2
- #define _PSPLINE_5_H_INCLUDED_
3
-
4
- template <typename T>
5
- void poly_new_subst(int n, T **w)
6
- {
7
- for (int i = 0; i < n; ++i) w[i] = NULL;
8
- }
9
-
10
- template <typename T, class... Args>
11
- void poly_new_subst(int n, T **w, const T *car, const Args... cdr)
12
- {
13
- w[0] = new T(*car); if (n > 1) poly_new_subst(n-1, &w[1], cdr...);
14
- }
15
-
16
- /*******************************************************************************
17
- define poly_spline[base_spline1*,...base_splineN*]
18
- *******************************************************************************/
19
- template <typename S = double> class poly_spline
20
- {
21
-
22
- int N; base_spline<S> **base;
23
-
24
- public:
25
- struct values_ {
26
- Int imax, icox, rank, jisu, shuki;
27
- carray_view<S> *knots;
28
- values_(poly_spline<S>& own, int as) :
29
- imax(own.Imax(as)), icox(own.Icox(as)),
30
- rank(own.Rank() ), jisu(own.Jisu() ), shuki(own.Shuki())
31
- {
32
- size_t n = own.Grid();
33
- knots = new carray_view<S>(n, own.Maxq(), NULL);
34
- for (size_t i = 0; i < n; i++)
35
- (*knots)[i] = own[i].Knots();
36
- }
37
- ~values_() { delete knots; }
38
- } *values;
39
-
40
- // constructor
41
- poly_spline() : base(NULL), values(NULL) {}
42
- poly_spline(const comb_array<S>& x, const Int& n, const Int& j, const Int& s) : N(x.grid())
43
- {
44
- base = new base_spline<S>*[N];
45
- for (int i = 0; i < N; i++)
46
- base[i] = new base_spline<S>(n[i], x[i], j[i], -s[i]%2);
47
- values = new values_(*this, n.unit_size());
48
- }
49
- template <class... Args>
50
- poly_spline(int k, const base_spline<S> *bsc, Args... bsd)
51
- : N(sizeof...(bsd)+1), base(new base_spline<S>*[sizeof...(bsd)+1])
52
- {
53
- base[0] = new base_spline<S>(*bsc);
54
- if (N > 1) poly_new_subst(N-1, &base[1], bsd...);
55
- values = new values_(*this, k);
56
- }
57
- poly_spline(int k, const poly_spline<S> *ps, const base_spline<S> *bs)
58
- : N(ps->Grid()+1), base(new base_spline<S>*[ps->Grid()+1])
59
- {
60
- for (int i = 0; i < N-1; i++) {
61
- const base_spline<S>& b = (*ps)[i];
62
- base[i] = new base_spline<S>(b);
63
- }
64
- base[N-1] = new base_spline<S>(*bs);
65
- values = new values_(*this, k);
66
- }
67
- poly_spline(int k, const base_spline<S> *bs, const poly_spline<S> *ps)
68
- : N(ps->Grid()+1), base(new base_spline<S>*[ps->Grid()+1])
69
- {
70
- base[0] = new base_spline<S>(*bs);
71
- for (int i = 1; i < N; i++) {
72
- const base_spline<S>& b = (*ps)[i-1];
73
- base[i] = new base_spline<S>(b);
74
- }
75
- values = new values_(*this, k);
76
- }
77
- poly_spline(int k, const base_spline<S>& bsc)
78
- : N(1), base(new base_spline<S>*[1])
79
- {
80
- base[0] = new base_spline<S>(bsc);
81
- values = new values_(*this, k);
82
- }
83
- // copy constructor
84
- poly_spline(const poly_spline& p) : N(p.N), base(new base_spline<S>*[p.N])
85
- {
86
- for (int i = 0; i < N; i++)
87
- base[i] = new base_spline<S>(*p.base[i]);
88
- values = new values_(*this, p.values->imax.unit_size());
89
- }
90
- // destructor
91
- ~poly_spline() {delete[] base; delete values;}
92
- // substitution operator
93
- poly_spline& operator=(const poly_spline& p)
94
- {
95
- if (this != &p) {
96
- delete[] base;
97
- N = p.N; base = new base_spline<S>*[p.N];
98
- for (int i = 0; i < N; i++) {
99
- base[i] = new base_spline<S>(*p.base[i]);
100
- } delete values;
101
- values = new values_(*this, p.values->imax.unit_size());
102
- }
103
- return *this;
104
- }
105
-
106
- marray<S> gyoretsu(base_spline<S> *base, int a, const S *x)
107
- {
108
- int imax = base->Imax();
109
- marray<S> bd(imax, imax);
110
- base->gyoretu(bd, a, x);
111
- return bd;
112
- }
113
-
114
- marray<S> gyoretu(const Int& a, const comb_array<S>& x)
115
- {
116
- marray<S> res = gyoretsu(base[0], a[0], x[0]);
117
- for (int i = 1; i < N; ++i) {
118
- res = res ^ gyoretsu(base[i], a[i], x[i]);
119
- }
120
- return res;
121
- }
122
-
123
- comp_array<S> basis(const poly<S>& t, const int *jb = NULL) const
124
- {
125
- int s[N*2];
126
- int size = this->values->rank.comb_size();
127
- S data[size], *p = data;
128
- for (int i = 0; i < N; i++) {
129
- parray<S> bc = base[i]->basis(t[i], jb ? jb[i] : 0);
130
- s[i] = bc(0); s[i+N] = bc(1);
131
- S *dat = *bc;
132
- for (int j = 0; j < bc(1); ++j) *p++ = dat[j];
133
- }
134
- return comp_array<S>(data, N*2, s, 1);
135
- }
136
-
137
- comp_array<S> bases(const poly<S>& t, int jbn = 0) const
138
- {
139
- int s[N*2], K = jbn + 1;
140
- int size = this->values->rank.comb_size();
141
- S data[size * K], *p = data;
142
- for (int i = 0; i < N; i++) {
143
- parray<S> bc = base[i]->bases(t[i], jbn);
144
- s[i] = bc(0); s[i+N] = bc(1);
145
- int sz = bc(1) * K;
146
- S *dat = *bc;
147
- for (int j = 0; j < sz; ++j) *p++ = dat[j];
148
- }
149
- return comp_array<S>(data, N*2, s, K);
150
- }
151
-
152
- template <typename T>
153
- void sekibun(poly_view<T>& r, const poly_view<T>& clp, const poly<int>& h, const poly<S>& x) const
154
- {
155
- int offset[N+1], size[N+1];
156
- Size_t z = this->values->rank;
157
- S **sp = create_carray<S>(N, z);
158
- for (int i = 0; i < N; ++i) {
159
- S ql = (*base[i])[h[i]];
160
- S qm = (*base[i])[h[i] + 1];
161
- S qh = (x[i] < qm ? x[i] : qm) - ql;
162
- parray<S> pc = base[i]->bases(ql, base[i]->Jisu());
163
- offset[i] = pc(0); size[i] = pc(1);
164
- for (int j = 0; j < size[i]; j++) sp[i][j] = pc.saylor(j, qh);
165
- } offset[N] = 0; size[N] = 0;
166
- Int o = Int(offset,N);
167
- Int s = Int(size, N);
168
- int end = s.grid_size();
169
- for (int i = 0; i < end; ++i) {
170
- Int k = i % s, j = k + o;
171
- r += clp[j] * [](int N, T **p, Int& k) -> T {
172
- T u = 1.0;
173
- for (int i = 0; i < N; ++i) u *= p[i][k[i]];
174
- return u;
175
- } (N, sp, k);
176
- }
177
- FREE(sp);
178
- }
179
-
180
- base_spline<S>& operator[](int i) const {return *base[i];}
181
-
182
- int Grid() const {return N;}
183
-
184
- Int Kset(const poly<S>& x) const
185
- {
186
- int v[N];
187
- for (int i = 0; i < N; i++) v[i] = base[i]->Kset(x[i]);
188
- return Int(N, v, 0);
189
- }
190
-
191
- private:
192
-
193
- Int Imax(int as = 1) const
194
- {
195
- int v[N];
196
- for (int i = 0; i < N; i++) v[i] = base[i]->Imax();
197
- return Int(N, v, as);
198
- }
199
- Int Icox(int as = 1) const
200
- {
201
- int v[N];
202
- for (int i = 0; i < N; i++) v[i] = base[i]->Icox();
203
- return Int(N, v, as);
204
- }
205
- Int Rank() const
206
- {
207
- int v[N];
208
- for (int i = 0; i < N; i++) v[i] = base[i]->Rank();
209
- return Int(N, v, 1);
210
- }
211
- Int Jisu() const
212
- {
213
- int v[N];
214
- for (int i = 0; i < N; i++) v[i] = base[i]->Jisu();
215
- return Int(N, v, 0);
216
- }
217
- Int Shuki() const
218
- {
219
- int v[N];
220
- for (int i = 0; i < N; i++) v[i] = base[i]->Shuki();
221
- return Int(N, v, 0);
222
- }
223
- size_t *Maxq() const
224
- {
225
- size_t *vp = new size_t[N];
226
- for (int i = 0; i < N; i++) vp[i] = base[i]->Maxq();
227
- return vp;
228
- }
229
- // end poly_spline
230
- };
231
-
232
- template <class T, class S> class bspline;
233
- /*******************************************************************************
234
- N変数K次元パラメトリック リーゼンフェルト スプライン補間
235
- int N : number of parameters (Grid)
236
- typename S : poly<S,N> = (s, t, u, ...)
237
- int K : number of axis (Atom)
238
- typename T : poly<T,K> = (x, y, z, ...)
239
- --------------------------------------------------------------------------------
240
- パラメトリックスプライン (曲面補間) s = {0,...}
241
- パラメトリック周期スプライン (閉曲面補間)s = {1,...}
242
- リーゼンフェルトスプライン (曲面補間) s = {2,...}
243
- リーゼンフェルト周期スプライン(閉曲面補間)s = {3,...}
244
- *******************************************************************************/
245
- template <typename T, typename S = double>
246
- class pspline : public poly_spline<S>
247
- {
248
-
249
- int K; T *clp;
250
-
251
- public:
252
- // constructor
253
- pspline():clp(NULL){}
254
- pspline(const poly_array<T>&, const comb_array<S>&, const Int&, const Int&);
255
- template <class... Args>
256
- pspline(int k, T *v, Args... bset)
257
- : poly_spline<S>(k, bset...), K(k), clp(v) {}
258
- pspline(const bspline<T,S>& bs)
259
- : poly_spline<S>(bs.Unit_size(), base_spline<S>(bs)), K(bs.Unit_size())
260
- {
261
- const Int& c = poly_spline<S>::values->icox;
262
- int s = c.data_size();
263
- clp = new T[s];
264
- memcpy(clp, (T*)bs, s * sizeof(T));
265
- }
266
- pspline(const pspline&);
267
- // destructor
268
- ~pspline() { delete[] clp; }
269
- // operator
270
- pspline& operator=(const pspline&);
271
- poly_array<T> operator[](S t) const { return (*this)(t); }
272
- poly_array<T> operator()(S, int = 0) const;
273
- poly_array<T> operator[](const poly<S>& p) const {return (*this)(p);}
274
- poly_array<T> operator()(const poly<S>&, const int* = NULL) const;
275
- poly_array<T> operator()(const poly<S>&, int, T*) const;
276
- poly_array<T> sekibun(const poly<S>&) const;
277
- int Unit_size() const {return K;}
278
- operator T* () const {return clp;}
279
- };
280
-
281
- template <typename T, typename S>
282
- pspline<T,S>::pspline(const poly_array<T>& p, const comb_array<S>& x, const Int& j, const Int& s)
283
- : poly_spline<S>(x, Int(p), j, s), K(p.unit_size())
284
- {
285
- const Int& a = poly_spline<S>::values->imax;
286
- const Int& c = poly_spline<S>::values->icox;
287
- T *alp = clp = new T[c.data_size()];
288
- poly_view<T> alv(alp, a), clv(clp, c);
289
- if (s < 2) {
290
- marray<S> bd = poly_spline<S>::gyoretu(a, x);
291
- marray_lu_view<S> lu(bd);
292
- lu.solve((T*)p, alp, K);
293
- } else
294
- memcpy(alp, (T*)p, p.data_size() * sizeof(T));
295
- clv = alv;
296
- }
297
- // copy constructor
298
- template <typename T, typename S>
299
- pspline<T,S>::pspline(const pspline& ps) : poly_spline<S>(ps), K(ps.K)
300
- {
301
- const Int& c = poly_spline<S>::values->icox;
302
- int len = c.data_size();
303
- clp = new T[len];
304
- memcpy(clp, (T*)ps, len * sizeof(T));
305
- }
306
- // substitution operator
307
- template <typename T, typename S>
308
- pspline<T,S>& pspline<T,S>::operator=(const pspline& ps)
309
- {
310
- if (this != &ps) {
311
- delete clp;
312
- poly_spline<S>::operator=(ps); K = ps.K;
313
- const Int& c = poly_spline<S>::values->icox;
314
- int len = c.data_size();
315
- clp = new T[len];
316
- memcpy(clp, (T*)ps, len * sizeof(T));
317
- }
318
- return *this;
319
- }
320
-
321
- template <typename T, typename S>
322
- poly_array<T> pspline<T,S>::operator()(const poly<S>& t, const int *jb) const
323
- {
324
- if (jb) {
325
- Int jbn(t.grid(), jb, 0);
326
- if (!(poly_spline<S>::values->jisu >= jbn))
327
- throw "out of range, pspline()";
328
- }
329
- T result[K]; for (int i = 0; i < K; ++i) result[i] = 0;
330
- poly_view<T> res(result, K);
331
- comp_array<S> pc = poly_spline<S>::basis(t, jb);
332
- const Int& c = poly_spline<S>::values->icox;
333
- poly_view<T> clv(clp, c);
334
- Int offset = pc.offset(), size = pc.size();
335
- int s = size.grid_size();
336
- for (int i = 0; i < s; ++i)
337
- {
338
- Int k = i % size, l = k + offset;
339
- res += clv[l] * pc[k = 1][0];
340
- }
341
- return poly_array<T>(result, K);
342
- }
343
-
344
- template <typename T, typename S>
345
- poly_array<T> pspline<T,S>::operator()(const poly<S>& t, int jbn, T *ds) const
346
- {
347
- if (!(poly_spline<S>::values->jisu >= jbn))
348
- throw "out of range, pspline()";
349
- T result[K]; for (int i = 0; i < K; ++i) result[i] = 0;
350
- poly_view<T> res(result, K);
351
- comp_array<S> pc = poly_spline<S>::bases(t, jbn);
352
- const Int& c = poly_spline<S>::values->icox;
353
- poly_view<T> clv(clp, c);
354
- Int offset = pc.offset(), size = pc.size();
355
- int s = size.grid_size();
356
- for (int i = 0; i < s; ++i)
357
- {
358
- Int k = i % size, l = k + offset;
359
- res += clv[l] * pc[k = jbn + 1][ds];
360
- }
361
- return poly_array<T>(result, K);
362
- }
363
-
364
- template <typename T, typename S>
365
- poly_array<T> pspline<T,S>::sekibun(const poly<S>& t) const
366
- {
367
- const Int& c = poly_spline<S>::values->icox;
368
- const Int& j = poly_spline<S>::values->jisu;
369
- Int n = poly_spline<S>::Kset(t) - j + 1;
370
- int Imax = n.grid_size();
371
- poly_view<T> clw(clp, c);
372
- int a = c.unit_size();
373
- T result[a]; for (int i = 0; i < a; i++) result[i] = 0;
374
- poly_view<T> R(result, a);
375
- for (int i = 0; i < Imax; ++i) {
376
- Int h = i % n + j;
377
- poly_spline<S>::sekibun(R, clw, h, t);
378
- }
379
- return poly_array<T>(result, a);
380
- }
381
-
382
- template <typename T, typename S>
383
- poly_array<T> pspline<T,S>::operator()(S t, int b) const
384
- {
385
- int N = this->Grid();
386
- S w[N+1]; for (int i = 0; i < N; i++) w[i] = t; w[N] = 0;
387
- poly<S> u(w, N);
388
- if (!(poly_spline<S>::values->jisu >= b))
389
- throw "out of range, pspline()";
390
- T result[K]; for (int i = 0; i < K; ++i) result[i] = 0;
391
- poly_view<T> res(result, K);
392
- comp_array<S> pc = poly_spline<S>::bases(u, b);
393
- const Int& c = poly_spline<S>::values->icox;
394
- poly_view<T> clv(clp, c);
395
- Int offset = pc.offset(), size = pc.size();
396
- int s = size.grid_size();
397
- for (int i = 0; i < s; ++i)
398
- {
399
- Int k = i % size, l = k + offset;
400
- res += clv[l] * pc[k = b + 1][b];
401
- }
402
- return poly_array<T>(result, K);
403
- }
404
-
405
- // 1変数N次元パラメトリックスプライン
406
- typedef pspline<double,double> Pspline;
407
- // 1変数N次元パラメトリックスプライン
408
- typedef pspline<double,double> Pspline2;
409
-
410
- /*******************************************************************************
411
- 1変数多次元パラメトリックスプライン
412
- *******************************************************************************/
413
- template <class T = double, class S = T> class bspline : public base_spline<S>
414
- {
415
- int K; T *clp;
416
-
417
- public:
418
- // constructor
419
- bspline(const poly_array<T>&, int, S*, int, int = 0, int* = NULL);
420
- bspline(const bspline&);
421
- // destructor
422
- ~bspline() { delete clp; }
423
- // operator
424
- bspline& operator=(const bspline&);
425
- poly_array<T> operator[](S t) const {return (*this)(t);}
426
- poly_array<T> operator()(S, int = 0) const;
427
- poly_array<T> sekibun(S) const;
428
- T line_element(S) const;
429
- bspline *line_integral(T(*)(poly_array<S>&), int, S*, S = 0, T = 0) const;
430
- int Unit_size() const {return K;}
431
- operator T* () const {return clp;}
432
- };
433
- /*******************************************************************************
434
- 1変数パラメトリックスプライン コンストラクタ
435
- --------------------------------------------------------------------------------
436
- パラメトリックスプライン (曲線補間) s = 0
437
- パラメトリック周期スプライン (閉曲線補間)s = 1
438
- リーゼンフェルトスプライン (曲線補間) s = 2
439
- リーゼンフェルト周期スプライン(閉曲線補間)s = 3
440
- *******************************************************************************/
441
- template <class T, class S>
442
- bspline<T,S>::bspline(
443
- const poly_array<T>& p, // Vector Array<1>, [P0,...,Pn-1];
444
- int n, S* x, // Variables, [X0,...,Xn-1];
445
- int j, // Dimension
446
- int s, // Type parameter
447
- int *d // Differential rank, [D0,...,Dn-1];
448
- )
449
- : base_spline<S>(n, x, j, p(0) - n - (s%2)), K(p.unit_size())
450
- {
451
- int a = base_spline<S>::imax;
452
- int c = base_spline<S>::icox;
453
- T *alp = clp = new T[c * K];
454
- if (s < 2) {
455
- marray<S> bd(a, a);
456
- base_spline<S>::gyoretu((S**)bd, a, x, d); //係数行列を作成
457
- marray_lu_view<S> lu(bd);
458
- lu.solve((T*)p, alp, K);
459
- } else
460
- memcpy(alp, (T*)p, a * K * sizeof(T));
461
- poly_view<T> alv(alp, Colon, a, K);
462
- poly_view<T> clv(clp, Colon, c, K);
463
- clv = alv;
464
- }
465
-
466
- template <class T, class S>
467
- bspline<T,S>::bspline(const bspline& s) : base_spline<S>(s), K(s.K)
468
- {
469
- int c = base_spline<S>::icox;
470
- clp = new T[c * K];
471
- memcpy(clp, (T*)s, c * K * sizeof(T));
472
- }
473
-
474
- template <class T, class S>
475
- bspline<T,S>& bspline<T,S>::operator=(const bspline& s)
476
- {
477
- if (this != &s) {
478
- base_spline<S>::operator=(s);
479
- K = s.K;
480
- delete clp;
481
- int c = base_spline<S>::icox;
482
- clp = new T[c * K];
483
- memcpy(clp, (T*)s, c * K * sizeof(T));
484
- }
485
- return *this;
486
- }
487
-
488
- template <typename T, typename S>
489
- void sekibun(const bspline<T,S>& p, S t, const poly_view<T>& alp, int Jsk, poly_view<T>& sek)
490
- {
491
- const base_spline<S>& base = p;
492
- const Int& size = alp;
493
- int ks, kset, k = base.Rank() + Jsk;
494
- S b[k], *q = base.Knots();
495
- ks = deboor<S>(base.Rank(), q, base.Icox(), t, b, kset, k);
496
- poly_view<T> *a[2], *w = new poly_view<T>[2*(kset+1)];
497
- a[0] = w; a[1] = &w[kset+1];
498
- for (int i = 0; i <= kset; ++i) {
499
- Int k = i % size;
500
- a[Jsk%2][i] = alp[k]; a[(Jsk+1)%2][i] = sek;
501
- }
502
- while (Jsk) {
503
- poly_view<T> *a0 = a[Jsk%2], *a1 = a[(Jsk+1)%2];
504
- for (int i = 0; i <= kset; ++i) {
505
- if (i == 0) a1[i] = 0.0;
506
- else a1[i] = a1[i-1];
507
- a1[i] += a0[i] * ((q[i+(k-Jsk)] - q[i]) / S(k-Jsk));
508
- }
509
- Jsk--;
510
- }
511
- for (int i = ks > 0 ? ks : 0; i <= kset; ++i)
512
- sek += a[0][i] * b[i-ks];
513
- delete[] w;
514
- }
515
-
516
- //
517
- // 1変数パラメトリックスプライン関数値の計算(曲線補間)
518
- //
519
-
520
- template <class T, class S>
521
- poly_array<T> bspline<T,S>::operator()(S t, int b) const
522
- {
523
- if (b > base_spline<S>::jisu)
524
- throw "out of range, bspline value";
525
- T result[K]; for (int i = 0; i < K; ++i) result[i] = 0;
526
- poly_view<T> res(result, size_t(K));
527
- Int c(Colon, base_spline<S>::icox, K);
528
- poly_view<T> clv(clp, c);
529
- if (b >= 0) {
530
- parray<S> bc = base_spline<S>::basis(t, b);
531
- Int offset(1, bc(0), 0), size(1, bc(1), 0);
532
- int s = size.grid_size();
533
- for (int i = 0; i < s; ++i)
534
- {
535
- Int k = i % size, l = k + offset;
536
- res += clv[l] * bc[0][i];
537
- }
538
- } else ::sekibun<T,S>(*this, t, clv, -b, res);
539
- return poly_array<T>(result, K);
540
- }
541
-
542
- template <class T, class S>
543
- poly_array<T> bspline<T,S>::sekibun(S t) const
544
- {
545
- T result[K]; for (int i = 0; i < K; ++i) result[i] = 0.0;
546
- base_spline<S>::sekibun(t, clp, K, result);
547
- return poly_array<T>(result, K);
548
- }
549
-
550
- template <class T, class S>
551
- T bspline<T,S>::line_element(S t) const
552
- {
553
- poly_array<T> r = (*this)(t, 1);
554
- T s = 0;
555
- for (int i = 0; i < K; ++i) s += r[i] * r[i];
556
- return sqrt(s);
557
- }
558
-
559
- template <class T, class S>
560
- bspline<T,S> *bspline<T,S>::line_integral(T(*F)(poly_array<S>&), int n, S *u, S x, T y) const
561
- {
562
- int N = n+1, D[N]; S X[N]; T Y[N];
563
- for (int i = 0; i < n; i++) D[i] = 1; D[n] = 0;
564
- for (int i = 0; i < n; i++) {
565
- poly_array<S> U = (*this)[u[i]];
566
- X[i] = u[i];
567
- Y[i] = F(U) * this->line_element(u[i]);
568
- } X[n] = x;
569
- Y[n] = y;
570
- poly_array<T> Ya(Y, 1, N, 1);
571
- return new bspline<T,S>(Ya, n, X, base_spline<S>::jisu, 0, D);
572
- }
573
-
574
- template <class T, class S>
575
- pspline<T,S> operator * (const bspline<T,S>& bs1, const bspline<T,S>& bs2)
576
- {
577
- int k1 = bs1.Unit_size(), k2 = bs2.Unit_size();
578
- assert(k1 == k2);
579
- int c1 = bs1.Icox(), c2 = bs2.Icox();
580
- T *cp1 = bs1, *cp2 = bs2, *cp3 = new T[c1*c2*k1];
581
- for (int i = 0; i < k1; i++) {
582
- varray_view<T> v1(cp1+i, c1, k1), v2(cp2+i, c2, k2), v3(cp3+i, c1*c2, k1);
583
- kronecker(v1, v2, v3);
584
- }
585
- const base_spline<S>& bt1 = bs1;
586
- const base_spline<S>& bt2 = bs2;
587
- return pspline<T,S>(k1, cp3, &bt1, &bt2);
588
- }
589
-
590
- template <class T, class S>
591
- pspline<T,S> operator * (const pspline<T,S>& ps, const bspline<T,S>& bs2)
592
- {
593
- int k2 = bs2.Unit_size(), c2 = bs2.Icox();
594
- const poly_spline<S>& ps1 = ps;
595
- const Int& c = ps1.values->icox;
596
- int k1 = c.unit_size(), c1 = c.grid_size();
597
- assert(k1 == k2);
598
- T *cp1 = ps, *cp2 = bs2, *cp3 = new T[c1*c2*k2];
599
- for (int i = 0; i < k1; i++) {
600
- varray_view<T> v1(cp1+i, c1, k1), v2(cp2+i, c2, k2), v3(cp3+i, c1*c2, k1);
601
- kronecker(v1, v2, v3);
602
- }
603
- const base_spline<S>& bt2 = bs2;
604
- return pspline<T,S>(k2, cp3, &ps1, &bt2);
605
- }
606
-
607
- template <class T, class S>
608
- pspline<T,S> operator * (const bspline<T,S>& bs1, const pspline<T,S>& ps)
609
- {
610
- int k1 = bs1.Unit_size(), c1 = bs1.Icox();
611
- const poly_spline<S>& ps2 = ps;
612
- const Int& c = ps2.values->icox;
613
- int k2 = c.unit_size(), c2 = c.grid_size();
614
- assert(k1 == k2);
615
- T *cp1 = bs1, *cp2 = ps, *cp3 = new T[c1*c2*k1];
616
- for (int i = 0; i < k1; i++) {
617
- varray_view<T> v1(cp1+i, c1, k1), v2(cp2+i, c2, k2), v3(cp3+i, c1*c2, k1);
618
- kronecker(v1, v2, v3);
619
- }
620
- const base_spline<S>& bt1 = bs1;
621
- return pspline<T,S>(k1, cp3, &bt1, &ps2);
622
- }
623
- //
624
- // misc
625
- //
626
- // 偏微分プロット
627
- template <class T, class S = double>
628
- int plot(const pspline<T,S>&, const comb_array<S>&, S**, T**, int, const int* = NULL);
629
- // 全微分プロット
630
- template <class T, class S = double>
631
- int plot(const pspline<T,S>&, const comb_array<S>&, S**, T**, int, int, S*);
632
- // 1変数関数積プロット
633
- template <class T, class S = double>
634
- int plot(const pspline<T,S>&, int, S*, S**, T**, int, int = 0);
635
- // 1変数関数プロット(インデックス)
636
- template <class T, class S = double>
637
- int plot(const bspline<T,S>&, const comb_array<S>&, S**, T**, int, int = 0);
638
- // 1変数関数プロット
639
- template <class T, class S = double>
640
- int plot(const bspline<T,S>&, int, S*, S**, T**, int, int = 0);
641
-
642
- #endif
1
+ #ifndef _PSPLINE_H_INCLUDED_
2
+ #define _PSPLINE_H_INCLUDED_
3
+
4
+ template <typename T>
5
+ void poly_new_subst(int n, T **w)
6
+ {
7
+ for (int i = 0; i < n; ++i) w[i] = NULL;
8
+ }
9
+
10
+ template <typename T, class... Args>
11
+ void poly_new_subst(int n, T **w, const T *car, const Args... cdr)
12
+ {
13
+ w[0] = new T(*car); if (n > 1) poly_new_subst(n-1, &w[1], cdr...);
14
+ }
15
+
16
+ /*******************************************************************************
17
+ define poly_spline[base_spline1*,...base_splineN*]
18
+ *******************************************************************************/
19
+ template <typename S = double> class poly_spline
20
+ {
21
+ int N; base_spline<S> **base;
22
+
23
+ public:
24
+
25
+ struct values_ {
26
+ Int imax, icox, rank, jisu, shuki;
27
+ carray_view<S> *knots;
28
+ values_(poly_spline<S>& own, int as, int at) :
29
+ imax(own.Imax(as, at)), icox(own.Icox(as, at)),
30
+ rank(own.Rank(at) ), jisu(own.Jisu() ), shuki(own.Shuki())
31
+ {
32
+ size_t n = own.Grid();
33
+ knots = new carray_view<S>(n, own.Maxq(), at, NULL);
34
+ S **index = *knots;
35
+ for (size_t i = 0; i < n; i++) index[i] = own[i].Knots();
36
+ }
37
+ ~values_() { delete knots; }
38
+ } *values;
39
+
40
+ // constructor
41
+ poly_spline() : base(NULL), values(NULL) {}
42
+ poly_spline(const comb_array<S>& x, const Int& n, const int *j, const int *s) : N(x.grid())
43
+ {
44
+ base = new base_spline<S>*[N];
45
+ for (int i = 0; i < N; i++)
46
+ base[i] = new base_spline<S>(n[i], x[i], j[i], -s[i]%2);
47
+ values = new values_(*this, n[N], x.atom());
48
+ }
49
+ template <class... Args>
50
+ poly_spline(int k, int a, const base_spline<S> *bsc, Args... bsd)
51
+ : N(sizeof...(bsd)+1), base(new base_spline<S>*[sizeof...(bsd)+1])
52
+ {
53
+ base[0] = new base_spline<S>(*bsc);
54
+ if (N > 1) poly_new_subst(N-1, &base[1], bsd...);
55
+ values = new values_(*this, k, a);
56
+ }
57
+ poly_spline(int k, int a, const poly_spline<S> *ps, const base_spline<S> *bs)
58
+ : N(ps->Grid()+1), base(new base_spline<S>*[ps->Grid()+1])
59
+ {
60
+ for (int i = 0; i < N-1; i++) {
61
+ const base_spline<S>& b = (*ps)[i];
62
+ base[i] = new base_spline<S>(b);
63
+ }
64
+ base[N-1] = new base_spline<S>(*bs);
65
+ values = new values_(*this, k, a);
66
+ }
67
+ poly_spline(int k, int a, const base_spline<S> *bs, const poly_spline<S> *ps)
68
+ : N(ps->Grid()+1), base(new base_spline<S>*[ps->Grid()+1])
69
+ {
70
+ base[0] = new base_spline<S>(*bs);
71
+ for (int i = 1; i < N; i++) {
72
+ const base_spline<S>& b = (*ps)[i-1];
73
+ base[i] = new base_spline<S>(b);
74
+ }
75
+ values = new values_(*this, k, a);
76
+ }
77
+ poly_spline(int k, int a, const base_spline<S>& bsc)
78
+ : N(1), base(new base_spline<S>*[1])
79
+ {
80
+ base[0] = new base_spline<S>(bsc);
81
+ values = new values_(*this, k, a);
82
+ }
83
+ // copy constructor
84
+ poly_spline(const poly_spline& p) : N(p.N), base(new base_spline<S>*[p.N])
85
+ {
86
+ for (int i = 0; i < N; i++)
87
+ base[i] = new base_spline<S>(*p.base[i]);
88
+ values = new values_(*this, p->imax.unit(), p->imax.atom());
89
+ }
90
+ // destructor
91
+ ~poly_spline() {delete[] base; delete values;}
92
+ // assignment operator
93
+ poly_spline& operator=(const poly_spline& p)
94
+ {
95
+ if (this != &p) {
96
+ delete[] base;
97
+ N = p.N; base = new base_spline<S>*[p.N];
98
+ for (int i = 0; i < N; i++) {
99
+ base[i] = new base_spline<S>(*p.base[i]);
100
+ } delete values;
101
+ values = new values_(*this, p->imax.unit(), p->imax.atom());
102
+ }
103
+ return *this;
104
+ }
105
+
106
+ values_* operator ->() const { return values; }
107
+
108
+ marray<S> gyoretsu(base_spline<S> *base, int a, const varray<S>& x)
109
+ {
110
+ size_t imax = base->Imax();
111
+ marray<S> bd(imax, imax, x.atom());
112
+ base->gyoretu(bd, a, x);
113
+ return bd;
114
+ }
115
+
116
+ marray<S> gyoretu(const Int& a, const comb_array<S>& x)
117
+ {
118
+ marray<S> res = gyoretsu(base[0], a[0], x[0]);
119
+ for (int i = 1; i < N; ++i) {
120
+ res = res ^ gyoretsu(base[i], a[i], x[i]);
121
+ }
122
+ return res;
123
+ }
124
+
125
+ comp_array<S> basis(const varray<S>& t, const int *jb = NULL) const
126
+ {
127
+ int s[(N+1)*2], a = t.atom();
128
+ int size = (*this)->rank.comb_size();
129
+ S data[size], *p = data;
130
+ for (int i = 0; i < N; i++) {
131
+ parray<S> bc = base[i]->basis(t[i], jb ? jb[i] : 0);
132
+ s[i] = bc(0); s[i+N] = bc(1);
133
+ S *bcd = *bc;
134
+ for (int j = 0; j < bc(1); ++j) for (int k = 0; k <= a; ++k) *p++ = bcd[j*(a+1)+k];
135
+ } s[N*2] = 1; s[N*2+1] = a;
136
+ return comp_array<S>(data, N*2, s);
137
+ }
138
+
139
+ comp_array<S> bases(const varray<S>& t, int jbn = 0) const
140
+ {
141
+ int s[(N+1)*2], K = jbn + 1, a = t.atom();
142
+ int size = (*this)->rank.comb_size();
143
+ S data[size * K], *p = data;
144
+ for (int i = 0; i < N; i++) {
145
+ parray<S> bc = base[i]->bases(t[i], jbn);
146
+ s[i] = bc(0); s[i+N] = bc(1);
147
+ int sz = bc(1) * K;
148
+ S *bcd = *bc;
149
+ for (int j = 0; j < sz; ++j) for (int k = 0; k <= a; ++k) *p++ = bcd[j*(a+1)+k];
150
+ } s[N*2] = K; s[N*2+1] = a;
151
+ return comp_array<S>(data, N*2, s);
152
+ }
153
+ // 不定積分([a,x]/[x,b],積分値,線型結合係数,節点番号(Kset(x)),端点(x))
154
+ template <typename T>
155
+ void sekibun(int, varray<T>&, const poly_view<T>&, const poly<int>&, const varray<S>&) const;
156
+ // 定積分(積分値,線型結合係数,区間番号,左端,右端)
157
+ template <typename T>
158
+ void integrate(varray<T>&, const poly_view<T>&, const poly<int>&, const varray<S>&, const varray<S>&) const;
159
+
160
+ base_spline<S>& operator[](int i) const {return *base[i];}
161
+
162
+ int Grid() const {return N;}
163
+
164
+ Int Kset(const varray<S>& x) const
165
+ {
166
+ int v[N+1]; v[N] = 0;
167
+ for (int i = 0; i < N; i++) v[i] = base[i]->Kset(x[i]);
168
+ return Int(N, v);
169
+ }
170
+
171
+ private:
172
+
173
+ Int Imax(int as = 1, int at = 0) const
174
+ {
175
+ int v[N+2]; v[N] = as; v[N+1] = at;
176
+ for (int i = 0; i < N; i++) v[i] = base[i]->Imax();
177
+ return Int(N+1, v);
178
+ }
179
+ Int Icox(int as = 1, int at = 0) const
180
+ {
181
+ int v[N+2]; v[N] = as; v[N+1] = at;
182
+ for (int i = 0; i < N; i++) v[i] = base[i]->Icox();
183
+ return Int(N+1, v);
184
+ }
185
+ Int Rank(int at = 0) const
186
+ {
187
+ int v[N+1]; v[N] = at;
188
+ for (int i = 0; i < N; i++) v[i] = base[i]->Rank();
189
+ return Int(N, v);
190
+ }
191
+ Int Jisu() const
192
+ {
193
+ int v[N+1]; v[N] = 0;
194
+ for (int i = 0; i < N; i++) v[i] = base[i]->Jisu();
195
+ return Int(N, v);
196
+ }
197
+ Int Shuki() const
198
+ {
199
+ int v[N+1]; v[N] = 0;
200
+ for (int i = 0; i < N; i++) v[i] = base[i]->Shuki();
201
+ return Int(N, v);
202
+ }
203
+ size_t *Maxq() const
204
+ {
205
+ size_t *vp = new size_t[N];
206
+ for (int i = 0; i < N; i++) vp[i] = base[i]->Maxq();
207
+ return vp;
208
+ }
209
+
210
+ }; // end poly_spline;
211
+
212
+ template <class T, class S> class bspline;
213
+ /*******************************************************************************
214
+ N変数K次元パラメトリック リーゼンフェルト スプライン補間
215
+ int N : number of parameters (Grid)
216
+ typename S : real<S,N> = (s, t, u, ...)
217
+ int K : number of axis (Atom)
218
+ typename T : real<T,K> = (x, y, z, ...)
219
+ --------------------------------------------------------------------------------
220
+ パラメトリックスプライン (曲面補間) s = {0,...}
221
+ パラメトリック周期スプライン (閉曲面補間)s = {1,...}
222
+ リーゼンフェルトスプライン (曲面補間) s = {2,...}
223
+ リーゼンフェルト周期スプライン(閉曲面補間)s = {3,...}
224
+ *******************************************************************************/
225
+ template <typename T = double, typename S = double>
226
+ class pspline : public poly_spline<S>
227
+ {
228
+ marray<T> *clp;
229
+
230
+ public:
231
+ // constructor
232
+ pspline():clp(NULL){}
233
+ pspline(const poly_array<T>&, const comb_array<S>&, const Int&, const int *, const int *);
234
+ pspline(marray<T> *mlp, const base_spline<S> *bs1, const base_spline<S> *bs2)
235
+ : poly_spline<S>(mlp->cols(), mlp->atom(), bs1, bs2), clp(mlp) {}
236
+ pspline(marray<T> *mlp, const poly_spline<S> *ps, const base_spline<S> *bs)
237
+ : poly_spline<S>(mlp->cols(), mlp->atom(), ps, bs), clp(mlp) {}
238
+ pspline(marray<T> *mlp, const base_spline<S> *bs, const poly_spline<S> *ps)
239
+ : poly_spline<S>(mlp->cols(), mlp->atom(), bs, ps), clp(mlp) {}
240
+ // copy constructor
241
+ pspline(const pspline& ps) : poly_spline<S>(ps), clp(new marray<T>(*ps.clp)){}
242
+ // destructor
243
+ ~pspline() { delete clp; }
244
+ // assignment operator
245
+ pspline& operator=(const pspline&);
246
+ // 関数積の値
247
+ varray<T> operator[](const real<S>& t) const { return (*this)(t); }
248
+ // 関数積の微分値
249
+ varray<T> operator()(const real<S>&, int = 0) const;
250
+ // 補間値(変数値)
251
+ varray<T> operator[](const varray<S>& p) const {return (*this)(p);}
252
+ // 偏微分値(変数値,偏微分階数)
253
+ varray<T> operator()(const varray<S>&, const int* = nullptr) const;
254
+ // 全微分値(変数値,微分階数,方向係数)
255
+ varray<T> operator()(const varray<S>&, int, const varray<S>&) const;
256
+ // 不定積分値(左端/右端,変数値)
257
+ varray<T> sekibun(int, const varray<S>&) const;
258
+ // 定積分値(左端変数値,右端変数値)
259
+ varray<T> integrate(const varray<S>&, const varray<S>&) const;
260
+ // property
261
+ int Unit() const {return clp->cols();}
262
+ int Atom() const {return clp->atom();}
263
+ operator marray<T>* () const { return clp; }
264
+ typename poly_spline<S>::values_* operator ->() const { return poly_spline<S>::values; }
265
+ };
266
+
267
+ template <typename T, typename S>
268
+ pspline<T,S>::pspline(
269
+ const poly_array<T>& p,
270
+ const comb_array<S>& x,
271
+ const Int& n,
272
+ const int *j,
273
+ const int *s
274
+ ) : poly_spline<S>(x, n, j, s)
275
+ {
276
+ int N = this->Grid();
277
+ const Int& a = (*this)->imax;
278
+ const Int& c = (*this)->icox;
279
+ clp = new marray<T>(c.unit_size(), c[N], c[N+1]);
280
+ int i; for (i = 0; i < N; ++i) if (s[i] >= 2) break;
281
+ if (i == N) {
282
+ marray<S> bd = this->gyoretu(a, x); //係数行列を作成
283
+ marray_lu_view<S> lu(bd);
284
+ marray_view<T> alu(**clp, a.unit_size(), a.unit(), a.atom());
285
+ marray_view<T> plu((T*)p, p.unit_size(), p.unit(), p.atom());
286
+ lu.solve(plu, alu);
287
+ } else {
288
+ int s = a.data_size();
289
+ // for (int i = 0; i < s; ++i) (**clp)[i] = ((T*)p)[i];
290
+ memcpy(**clp, (T*)p, s * sizeof(T));
291
+ }
292
+ poly_view<T> alu(**clp, a), clu(**clp, c);
293
+ clu = alu;
294
+ }
295
+ // assignment operator
296
+ template <typename T, typename S>
297
+ pspline<T,S>& pspline<T,S>::operator=(const pspline& ps)
298
+ {
299
+ if (this != &ps) {
300
+ delete clp;
301
+ poly_spline<S>::operator=(ps);
302
+ clp = new marray<T>(*ps.clp);
303
+ }
304
+ return *this;
305
+ }
306
+ // 偏微分値(変数値,偏微分階数リスト)
307
+ template <typename T, typename S>
308
+ varray<T> pspline<T,S>::operator()(const varray<S>& t, const int *jb) const
309
+ {
310
+ if (jb) {
311
+ int n = t.size(), z[n+1];
312
+ for (int i = 0; i < n; ++i) z[i] = jb[i]; z[n] = 0;
313
+ Int jbn(n, z);
314
+ if (!((*this)->jisu >= jbn)) throw "out of range, pspline()";
315
+ }
316
+ const Int& c = (*this)->icox;
317
+ size_t K = clp->cols(), A = clp->atom();
318
+ varray<T> result(T(), K, A);
319
+ comp_array<S> pc = this->basis(t, jb);
320
+ poly_view<T> clv(**clp, c);
321
+ Int offset = pc.offset(), size = pc.size();
322
+ int s = size.atom_size();
323
+ for (int i = 0; i < s; ++i)
324
+ {
325
+ Int k = i % size, l = k + offset;
326
+ result += clv[l] * pc[k = 1][0];
327
+ }
328
+ return result;
329
+ }
330
+ // 全微分値(変数値,微分階数,方向係数)
331
+ template <typename T, typename S>
332
+ varray<T> pspline<T,S>::operator()(const varray<S>& t, int jbn, const varray<S>& ds) const
333
+ {
334
+ if (!((*this)->jisu >= jbn)) throw "out of range, pspline()";
335
+
336
+ const Int& c = (*this)->icox;
337
+ size_t K = clp->cols(), A = clp->atom();
338
+ varray<T> result(T(), K, A);
339
+ comp_array<S> pc = this->bases(t, jbn);
340
+ poly_view<T> clv(**clp, c);
341
+ Int offset = pc.offset(), size = pc.size();
342
+ int s = size.atom_size();
343
+ for (int i = 0; i < s; ++i)
344
+ {
345
+ Int k = i % size, l = k + offset;
346
+ result += clv[l] * pc[k = jbn + 1][ds];
347
+ }
348
+ return result;
349
+ }
350
+ // 不定積分(区間積分)
351
+ template <typename S>
352
+ template <typename T> void poly_spline<S>::sekibun(int Q, // Q == 0 ? [a,x] : [x,b]
353
+ varray<T>& r, // 積分値を加算
354
+ const poly_view<T>& clp, // 線型結合係数
355
+ const poly<int>& h, // 積分区間の節点番号
356
+ const varray<S>& x // 積分範囲の端点
357
+ ) const
358
+ {
359
+ int offset[N+1], size[N+1]; size_t z[N];
360
+ const Int& zr = (*this)->rank;
361
+ for (int i = 0; i < N; ++i) z[i] = zr[i];
362
+ carray<S> sp(size_t(N), z, r.atom());
363
+ for (int i = 0; i < N; ++i) {
364
+ real<S> ql = (*base[i])[h[i]];
365
+ real<S> qm = (*base[i])[h[i] + 1];
366
+ real<S> q0 = (Q && ql < x[i]) ? x[i] : ql;
367
+ real<S> q1 = (Q || qm < x[i]) ? qm : x[i];
368
+ real<S> qh = q1 - q0;
369
+ parray<S> pc = base[i]->bases(q0, base[i]->Jisu());
370
+ offset[i] = pc(0); size[i] = pc(1);
371
+ for (int j = 0; j < size[i]; j++) sp[i][j] = pc.saylor(j, qh);
372
+ } offset[N] = 0; size[N] = 0;
373
+ Int o = Int(N, offset);
374
+ Int s = Int(N, size );
375
+ int end = s.grid_size(0);
376
+ for (int i = 0; i < end; ++i) {
377
+ Int k = i % s, j = k + o;
378
+ r += clp[j] * [](int N, const carray<S>& p, const Int& k) -> real<S> {
379
+ real<S> u(1.0, p.atom());
380
+ for (int i = 0; i < N; ++i) u *= p[i][k[i]];
381
+ return u;
382
+ } (N, sp, k);
383
+ }
384
+ }
385
+ // 定積分(区間積分)
386
+ template <typename S>
387
+ template <typename T> void poly_spline<S>::integrate(
388
+ varray<T>& r, // 積分値を加算
389
+ const poly_view<T>& clp, // 線型結合係数
390
+ const poly<int>& h, // 積分区間の節点番号
391
+ const varray<S>& x0, // 積分範囲の始点
392
+ const varray<S>& x1 // 積分範囲の終点
393
+ ) const
394
+ {
395
+ int offset[N+1], size[N+1]; size_t z[N];
396
+ const Int& zr = (*this)->rank;
397
+ for (int i = 0; i < N; ++i) z[i] = zr[i];
398
+ carray<S> sp(size_t(N), z, r.atom());
399
+ for (int i = 0; i < N; ++i) {
400
+ real<S> ql = (*base[i])[h[i]];
401
+ real<S> qm = (*base[i])[h[i] + 1];
402
+ real<S> q0 = (ql < x0[i] ? x0[i] : ql);
403
+ real<S> qh = (x1[i] < qm ? x1[i] : qm) - q0;
404
+ parray<S> pc = base[i]->bases(q0, base[i]->Jisu());
405
+ offset[i] = pc(0); size[i] = pc(1);
406
+ for (int j = 0; j < size[i]; j++) sp[i][j] = pc.saylor(j, qh);
407
+ } offset[N] = 0; size[N] = 0;
408
+ Int o = Int(N, offset);
409
+ Int s = Int(N, size );
410
+ int end = s.grid_size(0);
411
+ for (int i = 0; i < end; ++i) {
412
+ Int k = i % s, j = k + o;
413
+ r += clp[j] * [](int N, const carray<S>& p, const Int& k) -> real<S> {
414
+ real<S> u(1.0, p.atom());
415
+ for (int i = 0; i < N; ++i) u *= p[i][k[i]];
416
+ return u;
417
+ } (N, sp, k);
418
+ }
419
+ }
420
+ // 不定積分(左端/右端,変数値)
421
+ template <typename T, typename S>
422
+ varray<T> pspline<T,S>::sekibun(int Q, const varray<S>& t) const
423
+ {
424
+ #ifndef NDEBUG
425
+ size_t N = this->Grid();
426
+ #endif
427
+ assert(N == t.size());
428
+ const Int& c = (*this)->icox;
429
+ Int ks = this->Kset(t);
430
+ const Int& j = Q ? ks : (*this)->jisu;
431
+ Int n = Q ? ((c >> 1) = 0) - ks : ks - j + 1;
432
+ int Imax = n.grid_size(0);
433
+ varray<T> result(T(), c.unit(), c.atom());
434
+ poly_view<T> clv(**clp, c);
435
+ for (int i = 0; i < Imax; ++i) {
436
+ Int h = i % n + j;
437
+ poly_spline<S>::sekibun(Q, result, clv, h, t);
438
+ }
439
+ return result;
440
+ }
441
+ // 定積分
442
+ template <typename T, typename S>
443
+ varray<T> pspline<T,S>::integrate(const varray<S>& s, const varray<S>& t) const
444
+ {
445
+ #ifndef NDEBUG
446
+ size_t N = this->Grid();
447
+ #endif
448
+ assert(N == s.size() && N == t.size());
449
+ const Int& c = (*this)->icox;
450
+ Int ks = poly_spline<S>::Kset(s);
451
+ Int kt = poly_spline<S>::Kset(t);
452
+ Int n = kt - ks; n += 1;
453
+ int Imax = n.grid_size(0);
454
+ varray<T> result(T(), c.unit(), c.atom());
455
+ poly_view<T> clv(**clp, c);
456
+ for (int i = 0; i < Imax; ++i) {
457
+ Int h = i % n + ks;
458
+ poly_spline<S>::integrate(result, clv, h, s, t);
459
+ }
460
+ return result;
461
+ }
462
+ // 関数積の微分値
463
+ template <typename T, typename S>
464
+ varray<T> pspline<T,S>::operator()(const real<S>& t, int b) const
465
+ {
466
+ size_t N = this->Grid();
467
+ varray<S> u(N, t.atom());
468
+ for (size_t i = 0; i < N; i++) u[i] = t;
469
+ if (!((*this)->jisu >= b)) throw "out of range, pspline()";
470
+ const Int& c = (*this)->icox;
471
+ size_t K = clp->cols(), A = clp->atom();
472
+ varray<T> result(T(), K, A);
473
+ comp_array<S> pc = this->bases(u, b);
474
+ poly_view<T> clv(**clp, c);
475
+ Int offset = pc.offset(), size = pc.size();
476
+ int s = size.atom_size();
477
+ for (int i = 0; i < s; ++i)
478
+ {
479
+ Int k = i % size, l = k + offset;
480
+ result += clv[l] * pc[k = b + 1][b];
481
+ }
482
+ return result;
483
+ }
484
+
485
+ // 1変数N次元パラメトリックスプライン
486
+ typedef pspline<double,double> Pspline;
487
+ // 1変数N次元パラメトリックスプライン
488
+ typedef pspline<double,double> Pspline2;
489
+
490
+ /*******************************************************************************
491
+ 1変数多次元パラメトリックスプライン
492
+ *******************************************************************************/
493
+ template <class T = double, class S = double> class bspline : base_spline<S>
494
+ {
495
+ marray<T> *clp;
496
+
497
+ public:
498
+ // constructor
499
+ bspline() : base_spline<S>(), clp(NULL) {}
500
+ bspline(const poly_array<T>&, const varray<S>&, int, int, int = 0, int* = NULL);
501
+ // copy constructor
502
+ bspline(const bspline& bs) : base_spline<S>(bs), clp(new marray<T>(*bs.clp)) {}
503
+ // destructor
504
+ ~bspline() { delete clp; }
505
+ // assignment operator
506
+ bspline& operator=(const bspline&);
507
+ varray<T> operator[](const real<S>& t) const {return (*this)(t);}
508
+ varray<T> operator()(const real<S>&, int = 0) const;
509
+ varray<T> sekibun(const real<S>& t) const { return base_spline<S>::sekibun(t, *clp); }
510
+ real<T> line_element(const real<S>&) const;
511
+ bspline *line_integral(real<T>(*)(const varray<S>&), const comb_array<S>&, const real<S>& = real<S>(), const real<T>& = real<T>()) const;
512
+ base_spline<S> *Base() const { return (base_spline<S>*)this; }
513
+ int Rank() const { return base_spline<S>::Rank(); }
514
+ int Icox() const { return base_spline<S>::Icox(); }
515
+ int Jisu() const { return base_spline<S>::Jisu(); }
516
+ real<S> x_min() const { return base_spline<S>::x_min(); }
517
+ real<S> x_max() const { return base_spline<S>::x_max(); }
518
+ varray<S> Knots() const { return base_spline<S>::Knots(); }
519
+ parray<S> basis(const real<S>& t, int j) const { return base_spline<S>::basis(t,j); }
520
+ int Unit() const {return clp->cols();}
521
+ int Atom() const {return clp->atom();}
522
+ operator marray<T>* () const {return clp;}
523
+ base_spline<S> *Base() { return base_spline<S>::Base(); }
524
+ void print() {
525
+ base_spline<S>::print();
526
+ clp->print();
527
+ }
528
+ };
529
+ /*******************************************************************************
530
+ 1変数パラメトリックスプライン コンストラクタ
531
+ --------------------------------------------------------------------------------
532
+ パラメトリックスプライン (曲線補間) s = 0
533
+ パラメトリック周期スプライン (閉曲線補間)s = 1
534
+ リーゼンフェルトスプライン (曲線補間) s = 2
535
+ リーゼンフェルト周期スプライン(閉曲線補間)s = 3
536
+ *******************************************************************************/
537
+ template <class T, class S>
538
+ bspline<T,S>::bspline(
539
+ const poly_array<T>& p, // Vector Array<1>, [{P(0,1),...,P(0,K)},...,{P(n-1,1),...,P(n-1,K)}];
540
+ const varray<S>& x, // Variables, [X0,...,Xn-1];
541
+ int n,
542
+ int j, // Dimension
543
+ int s, // Type parameter
544
+ int *d // Differential rank, [D0,...,Dn-1];
545
+ )
546
+ : base_spline<S>(n, x, j, p.unit_size() - n - (s%2))
547
+ {
548
+ Int a{this->imax, (int)p.unit(), (int)p.atom()};
549
+ Int c{this->icox, int(p.unit()), int(p.atom())};
550
+ clp = new marray<T>(c.unit_size(), c[1], c[2]);
551
+ if (s < 2) {
552
+ marray<S> bd = this->gyoretu(a, x, d); //係数行列を作成
553
+ marray_lu_view<S> lu(bd);
554
+ marray_view<T> alu(**clp, a.unit_size(), a.unit(), a.atom());
555
+ marray_view<T> plu((T*)p, p.unit_size(), p.unit(), p.atom());
556
+ lu.solve(plu, alu);
557
+ } else {
558
+ int s = a.data_size();
559
+ // for (int i = 0; i < s; ++i) (**clp)[i] = ((T*)p)[i];
560
+ memcpy(**clp, (T*)p, s * sizeof(T));
561
+ }
562
+ poly_view<T> alu(**clp, a), clu(**clp, c);
563
+ clu = alu;
564
+ }
565
+
566
+ template <class T, class S>
567
+ bspline<T,S>& bspline<T,S>::operator=(const bspline& bs)
568
+ {
569
+ if (this != &bs) {
570
+ delete clp;
571
+ base_spline<S>::operator=(bs);
572
+ clp = new marray<T>(*bs.clp);
573
+ }
574
+ return *this;
575
+ }
576
+
577
+ template <typename T, typename S>
578
+ varray<T> sekibun(const bspline<T,S>& bs, const real<S>& t, const marray<T>& clp, int Jsk)
579
+ {
580
+ assert(Jsk < 0);
581
+ size_t K = clp.cols(), A = clp.atom();
582
+ parray<S> pc = bs.basis(t, Jsk);
583
+ int ks = pc(0), k = pc(1), kset = ks + k - 1;
584
+ varray<S> b = pc[0], q = bs.Knots();
585
+ marray<T> a(size_t(kset+1), K, A);
586
+ for (int i = 0; i <= kset; ++i) a[i] = clp[i];
587
+ while (Jsk < 0) {
588
+ varray<T> aw(T(), K, A);
589
+ for (int i = 0; i <= kset; ++i) {
590
+ real<S> w = (q[i+(k+Jsk)] - q[i]) / S(k+Jsk);
591
+ a[i] = aw + a[i] * w; aw = a[i];
592
+ }
593
+ Jsk++;
594
+ }
595
+ varray<T> sek(T(), K, A);
596
+ for (int i = (ks > 0 ? ks : 0); i <= kset; ++i) sek += a[i] * b[i-ks];
597
+ return sek;
598
+ }
599
+
600
+ //
601
+ // 1変数パラメトリックスプライン関数値の計算(曲線補間)
602
+ //
603
+
604
+ template <class T, class S>
605
+ varray<T> bspline<T,S>::operator()(const real<S>& t, int b) const
606
+ {
607
+ if (b > this->jisu) throw "out of range, bspline value";
608
+ size_t K = clp->cols(), A = clp->atom();
609
+ poly_view<T> clv(**clp, this->icox, int(K), int(A));
610
+ varray<T> result(T(), K, A);
611
+ if (b >= 0) {
612
+ parray<S> bc = this->basis(t, b);
613
+ Int offset = {bc(0), 0};
614
+ int end = bc(1);
615
+ for (int i = 0; i < end; ++i)
616
+ {
617
+ Int k = {i, 0};
618
+ result += clv[k + offset] * bc[0][i];
619
+ }
620
+ } else result = ::sekibun<T,S>(*this, t, *clp, b);
621
+ return result;
622
+ }
623
+
624
+ template <class T, class S>
625
+ real<T> bspline<T,S>::line_element(const real<S>& t) const
626
+ {
627
+ int K = clp->cols();
628
+ varray<T> r = (*this)(t, 1);
629
+ real<T> s(T(), t.atom());
630
+ for (int i = 0; i < K; ++i) s += r[i] * r[i];
631
+ return sqrt(s);
632
+ }
633
+
634
+ template <class T, class S>
635
+ bspline<T,S>* bspline<T,S>::line_integral(real<T>(*F)(const varray<S>&), const comb_array<S>& C, const real<S>& x, const real<T>& y) const
636
+ {
637
+ varray<S> u = C[0];
638
+ size_t A = u.atom();
639
+ int n = u.size(), N = n+1, D[N];
640
+ varray<S> X(size_t(N), A);
641
+ poly_array<T> Ya(N, 1, int(A));
642
+ const varray<T>& Y = *Ya;
643
+ for (int i = 0; i < n; i++) D[i] = 1; D[n] = 0;
644
+ for (int i = 0; i < n; i++) {
645
+ varray<S> U = (*this)[u[i]];
646
+ X[i] = u[i];
647
+ Y[i] = F(U) * this->line_element(u[i]);
648
+ } X[n] = x;
649
+ Y[n] = y;
650
+ return new bspline<T,S>(Ya, X, n, base_spline<S>::jisu, 0, D);
651
+ }
652
+
653
+ template <class T, class S>
654
+ pspline<T,S> operator * (const bspline<T,S>& bs1, const bspline<T,S>& bs2)
655
+ {
656
+ size_t k1 = bs1.Unit(), a1 = bs1.Atom();
657
+ #ifndef NDEBUG
658
+ size_t k2 = bs2.Unit(), a2 = bs2.Atom();
659
+ #endif
660
+ assert(k1 == k2 && a1 == a2);
661
+ const marray<T> *mp1 = bs1, *mp2 = bs2;
662
+ marray<T> *mp3 = new marray<T>(mp1->rows() * mp2->rows(), k1, a1);
663
+ for (size_t i = 0; i < k1; i++) {
664
+ varray<T> v1 = mp1->col(i), v2 = mp2->col(i), v3 = mp3->col(i);
665
+ kronecker(v1, v2, v3);
666
+ }
667
+ const base_spline<S> *bt1 = bs1.Base();
668
+ const base_spline<S> *bt2 = bs2.Base();
669
+ return pspline<T,S>(mp3, bt1, bt2);
670
+ }
671
+
672
+ template <class T, class S>
673
+ pspline<T,S> operator * (const pspline<T,S>& ps, const bspline<T,S>& bs)
674
+ {
675
+ size_t k1 = ps.Unit(), a1 = ps.Atom();
676
+ #ifndef NDEBUG
677
+ size_t k2 = bs.Unit(), a2 = bs.Atom();
678
+ #endif
679
+ assert(k1 == k2 && a1 == a2);
680
+ const marray<T> *mp1 = ps, *mp2 = bs;
681
+ marray<T> *mp3 = new marray<T>(mp1->rows() * mp2->rows(), k1, a1);
682
+ for (size_t i = 0; i < k1; i++) {
683
+ varray<T> v1 = mp1->col(i), v2 = mp2->col(i), v3 = mp3->col(i);
684
+ kronecker(v1, v2, v3);
685
+ }
686
+ const poly_spline<S>& ps1 = ps;
687
+ const base_spline<S> *bt2 = bs.Base();
688
+ return pspline<T,S>(mp3, &ps1, bt2);
689
+ }
690
+
691
+ template <class T, class S>
692
+ pspline<T,S> operator * (const bspline<T,S>& bs, const pspline<T,S>& ps)
693
+ {
694
+ size_t k1 = bs.Unit(), a1 = bs.Atom();
695
+ #ifndef NDEBUG
696
+ size_t k2 = ps.Unit(), a2 = ps.Atom();
697
+ #endif
698
+ assert(k1 == k2 && a1 == a2);
699
+ const marray<T> *mp1 = bs, *mp2 = ps;
700
+ marray<T> *mp3 = new marray<T>(mp1->rows() * mp2->rows(), k1, a1);
701
+ for (size_t i = 0; i < k1; i++) {
702
+ varray<T> v1 = mp1->col(i), v2 = mp2->col(i), v3 = mp3->col(i);
703
+ kronecker(v1, v2, v3);
704
+ }
705
+ const base_spline<S> *bt1 = bs.Base();
706
+ const poly_spline<S>& ps2 = ps;
707
+ return pspline<T,S>(mp3, bt1, &ps2);
708
+ }
709
+ //
710
+ // misc
711
+ //
712
+
713
+ template <typename U, typename T, typename S>
714
+ int plot_sub0(const U& B, int n, const varray<S>& x, varray<S>& Xp, marray<T>& Yp, int Dp, int b)
715
+ {
716
+ int K = B.Unit(), A = B.Atom();
717
+
718
+ int Npx = (n - 1) * Dp + 1;
719
+ Xp = varray<S>(size_t(Npx), size_t(A));
720
+ Yp = marray<T>(size_t(Npx), size_t(K), size_t(A));
721
+ for (int L = 1; L < n; L++) {
722
+ real<S> DT = (x[L] - x[L-1]) / S(Dp);
723
+ int N0 = (L == 1 ? 0 : 1);
724
+ for (int Nd = N0; Nd <= Dp; Nd++) {
725
+ int Np = Nd + (L-1) * Dp;
726
+ real<S> Tp = x[L-1] + Nd * DT;
727
+ Xp[Np] = Tp;
728
+ varray<T> Z = B(Tp, b);
729
+ for (int i = 0; i < K; ++i) Yp[Np][i] = Z[i];
730
+ }
731
+ }
732
+ return Npx;
733
+ }
734
+
735
+ template <typename T, typename S> class functor
736
+ {
737
+ int type, p; const int *bp; const varray<S>* jp;
738
+ public:
739
+ functor(int b) { type = 0; p = b; }
740
+ functor(const int *b) { type = 1; bp = b; }
741
+ functor(int j, const varray<S>& b) { type = 2; p = j; jp = &b; }
742
+ varray<T> apply(const bspline<T,S>& B, const varray<S>& s) const { return B(s[0], p); }
743
+ varray<T> apply(const pspline<T,S>& B, const varray<S>& s) const
744
+ {
745
+ varray<T> result;
746
+ if (type == 1) result = B(s, bp);
747
+ else result = B(s, p, *jp);
748
+ return result;
749
+ }
750
+ };
751
+
752
+ template <typename U, typename T, typename S>
753
+ int plot_sub(const U& B, const comb_array<S>& x, marray<S>& Xp, marray<T>& Yp, int Dp, const functor<T,S>& f)
754
+ {
755
+ poly_index<S> H(x, Dp);
756
+ const Int& n = x;
757
+ int N = n.grid(), K = B.Unit();
758
+ int Npx = H.index_size(), L = Npx;
759
+ Xp = marray<S>(size_t(Npx), size_t(N), x.atom());
760
+ Yp = marray<T>(size_t(Npx), size_t(K), B.Atom());
761
+ while (L--) {
762
+ int Np = H.index_value();
763
+ varray<S> Sp = H.get_value();
764
+ for (int i = 0; i < N; i++) Xp[Np][i] = Sp[i];
765
+ varray<T> Bp = f.apply(B, Sp);
766
+ for (int i = 0; i < K; i++) Yp[Np][i] = Bp[i];
767
+ ++H;
768
+ }
769
+ return Npx;
770
+ }
771
+ // 偏微分プロット
772
+ template <typename T, typename S> inline
773
+ int plot(const pspline<T,S>& B, const comb_array<S>& x, marray<S>& Xp, marray<T>& Yp, int Dp, const int *b = NULL)
774
+ {
775
+ functor<T,S> F(b);
776
+ return plot_sub<pspline<T,S> >(B, x, Xp, Yp, Dp, F);
777
+ }
778
+ // 全微分プロット
779
+ template <typename T, typename S> inline
780
+ int plot(const pspline<T,S>& B, const comb_array<S>& x, marray<S>& Xp, marray<T>& Yp, int Dp, int Jbn, const varray<S>& jb)
781
+ {
782
+ functor<T,S> F(Jbn, jb);
783
+ return plot_sub<pspline<T,S> >(B, x, Xp, Yp, Dp, F);
784
+ }
785
+ // 1変数関数積プロット
786
+ template <typename T, typename S> inline
787
+ int plot(const pspline<T,S>& B, int n, const varray<S>& x, varray<S>& Xp, marray<T>& Yp, int Dp, int b = 0)
788
+ {
789
+ return plot_sub0<pspline<T,S> >(B, n, x, Xp, Yp, Dp, b);
790
+ }
791
+ // 1変数関数プロット(インデックス)
792
+ template <typename T, typename S> inline
793
+ int plot(const bspline<T,S>& B, const comb_array<S>& x, marray<S>& Xp, marray<T>& Yp, int Dp, int Jbn = 0)
794
+ {
795
+ assert(x.grid() == 1);
796
+ functor<T,S> F(Jbn);
797
+ return plot_sub<bspline<T,S> >(B, x, Xp, Yp, Dp, F);
798
+ }
799
+ // 1変数関数プロット
800
+ template <typename T, typename S> inline
801
+ int plot(const bspline<T,S>& B, int n, const varray<S>& x, varray<S>& Xp, marray<T>& Yp, int Dp, int b = 0)
802
+ {
803
+ return plot_sub0<bspline<T,S> >(B, n, x, Xp, Yp, Dp, b);
804
+ }
805
+
806
+ #endif