pspline 5.0.2

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 (50) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +5 -0
  3. data/README.md +34 -0
  4. data/Rakefile +6 -0
  5. data/bin/console +14 -0
  6. data/bin/setup +8 -0
  7. data/ext/pspline/basis.cpp +351 -0
  8. data/ext/pspline/example/exbspline.ps +2194 -0
  9. data/ext/pspline/example/exbspline.rb +36 -0
  10. data/ext/pspline/example/excspline.ps +2985 -0
  11. data/ext/pspline/example/excspline.rb +36 -0
  12. data/ext/pspline/example/exdspline.ps +2846 -0
  13. data/ext/pspline/example/exdspline.rb +33 -0
  14. data/ext/pspline/example/exfspline.rb +66 -0
  15. data/ext/pspline/example/exfspline1.rb +40 -0
  16. data/ext/pspline/example/expspline.ps +3299 -0
  17. data/ext/pspline/example/expspline.rb +29 -0
  18. data/ext/pspline/example/expspline1.rb +29 -0
  19. data/ext/pspline/example/expspline2.rb +47 -0
  20. data/ext/pspline/example/exqspline.ps +2957 -0
  21. data/ext/pspline/example/exqspline.rb +31 -0
  22. data/ext/pspline/example/exqspline1.rb +31 -0
  23. data/ext/pspline/example/exqspline2.rb +50 -0
  24. data/ext/pspline/example/exqspline3.rb +51 -0
  25. data/ext/pspline/example/exrspline.ps +2812 -0
  26. data/ext/pspline/example/exrspline.rb +34 -0
  27. data/ext/pspline/example/exrspline1.rb +34 -0
  28. data/ext/pspline/example/exrspline2.rb +44 -0
  29. data/ext/pspline/example/exsspline.ps +1965 -0
  30. data/ext/pspline/example/exsspline.rb +35 -0
  31. data/ext/pspline/example/exsspline1.rb +35 -0
  32. data/ext/pspline/example/extspline.ps +2767 -0
  33. data/ext/pspline/example/extspline.rb +32 -0
  34. data/ext/pspline/extconf.rb +7 -0
  35. data/ext/pspline/fft.cpp +552 -0
  36. data/ext/pspline/include/basis/basis.h +137 -0
  37. data/ext/pspline/include/basis/fft.h +152 -0
  38. data/ext/pspline/include/basis/poly_array.h +1568 -0
  39. data/ext/pspline/include/basis/pspline.h +506 -0
  40. data/ext/pspline/include/basis/uspline.h +210 -0
  41. data/ext/pspline/include/basis/util.h +656 -0
  42. data/ext/pspline/include/bspline.h +377 -0
  43. data/ext/pspline/include/bspline_Config.h +2 -0
  44. data/ext/pspline/plotsub.cpp +132 -0
  45. data/ext/pspline/pspline.cpp +897 -0
  46. data/ext/pspline/util.cpp +483 -0
  47. data/lib/pspline.rb +6 -0
  48. data/lib/pspline/version.rb +3 -0
  49. data/pspline.gemspec +25 -0
  50. metadata +122 -0
@@ -0,0 +1,506 @@
1
+ #ifndef _PSPLINE_5_H_INCLUDED_
2
+ #define _PSPLINE_5_H_INCLUDED_
3
+
4
+ /*******************************************************************************
5
+ define poly_spline[base_spline1*,...base_splineN*]
6
+ *******************************************************************************/
7
+ template <typename S = double> class poly_spline
8
+ {
9
+
10
+ int N; base_spline<S> **base;
11
+
12
+ public:
13
+ struct values_ {
14
+ Int imax, icox, rank, jisu, shuki;
15
+ carray_view<S> *knots;
16
+ values_(poly_spline<S>& own, int as) :
17
+ imax(own.Imax(as)), icox(own.Icox(as)),
18
+ rank(own.Rank() ), jisu(own.Jisu() ), shuki(own.Shuki())
19
+ {
20
+ size_t n = own.Grid();
21
+ knots = new carray_view<S>(n, own.Maxq(), NULL);
22
+ for (size_t i = 0; i < n; i++)
23
+ (*knots)[i] = own[i].Knots();
24
+ }
25
+ ~values_() { delete knots; }
26
+ } *values;
27
+
28
+ // constructor
29
+ poly_spline(const comb_array<S>& x, const Int& n, const Int& j, const Int& s) : N(x.grid())
30
+ {
31
+ base = new base_spline<S>*[N];
32
+ for (int i = 0; i < N; i++)
33
+ base[i] = new base_spline<S>(n[i], x[i], j[i], -s[i]%2);
34
+ values = new values_(*this, n.unit_size());
35
+ }
36
+ // copy constructor
37
+ poly_spline(const poly_spline& p) : N(p.N)
38
+ {
39
+ for (int i = 0; i < N; i++)
40
+ base[i] = new base_spline<S>(*p.base[i]);
41
+ values = new values_(*this, p.values->imax.unit_size());
42
+ }
43
+ // destructor
44
+ ~poly_spline() {delete[] base; delete values;}
45
+ // substitution operator
46
+ poly_spline& operator=(const poly_spline& p)
47
+ {
48
+ if (this != &p) {
49
+ delete[] base;
50
+ int N = p.N;
51
+ for (int i = 0; i < N; i++) {
52
+ base[i] = base_spline<S>(*p.base[i]);
53
+ } delete values;
54
+ values = new values_(*this, p.values->imax.unit_size());
55
+ }
56
+ return *this;
57
+ }
58
+
59
+ marray<S> gyoretsu(base_spline<S> *base, int a, const S *x)
60
+ {
61
+ int imax = base->Imax();
62
+ marray<S> bd(imax, imax);
63
+ base->gyoretu(bd, a, x);
64
+ return bd;
65
+ }
66
+
67
+ marray<S> gyoretu(const Int& a, const comb_array<S>& x)
68
+ {
69
+ marray<S> res = gyoretsu(base[0], a[0], x[0]);
70
+ for (int i = 1; i < N; ++i) {
71
+ res = res ^ gyoretsu(base[i], a[i], x[i]);
72
+ }
73
+ return res;
74
+ }
75
+
76
+ comp_array<S> basis(const poly<S>& t, const int *jb = NULL) const
77
+ {
78
+ int s[N*2];
79
+ int size = this->values->rank.comb_size();
80
+ S data[size], *p = data;
81
+ for (int i = 0; i < N; i++) {
82
+ parray<S> bc = base[i]->basis(t[i], jb ? jb[i] : 0);
83
+ s[i] = bc(0); s[i+N] = bc(1);
84
+ S *dat = *bc;
85
+ for (int j = 0; j < bc(1); ++j) *p++ = dat[j];
86
+ }
87
+ return comp_array<S>(data, N*2, s, 1);
88
+ }
89
+
90
+ comp_array<S> bases(const poly<S>& t, int jbn = 0) const
91
+ {
92
+ int s[N*2], K = jbn + 1;
93
+ int size = this->values->rank.comb_size();
94
+ S data[size * K], *p = data;
95
+ for (int i = 0; i < N; i++) {
96
+ parray<S> bc = base[i]->bases(t[i], jbn);
97
+ s[i] = bc(0); s[i+N] = bc(1);
98
+ int sz = bc(1) * K;
99
+ S *dat = *bc;
100
+ for (int j = 0; j < sz; ++j) *p++ = dat[j];
101
+ }
102
+ return comp_array<S>(data, N*2, s, K);
103
+ }
104
+
105
+ template <typename T>
106
+ void sekibun(poly_view<T>& r, const poly_view<T>& clp, const poly<int>& h, const poly<S>& x) const
107
+ {
108
+ int offset[N+1], size[N+1];
109
+ Size_t z = this->values->rank;
110
+ S **sp = create_carray<S>(N, z);
111
+ for (int i = 0; i < N; ++i) {
112
+ S ql = (*base[i])[h[i]];
113
+ S qm = (*base[i])[h[i] + 1];
114
+ S qh = (x[i] < qm ? x[i] : qm) - ql;
115
+ parray<S> pc = base[i]->bases(ql, base[i]->Jisu());
116
+ offset[i] = pc(0); size[i] = pc(1);
117
+ for (int j = 0; j < size[i]; j++) sp[i][j] = pc.saylor(j, qh);
118
+ } offset[N] = 0; size[N] = 0;
119
+ Int o = Int(offset,N);
120
+ Int s = Int(size, N);
121
+ int end = s.grid_size();
122
+ for (int i = 0; i < end; ++i) {
123
+ Int k = i % s, j = k + o;
124
+ r += clp[j] * [](int N, T **p, Int& k) -> T {
125
+ T u = 1.0;
126
+ for (int i = 0; i < N; ++i) u *= p[i][k[i]];
127
+ return u;
128
+ } (N, sp, k);
129
+ }
130
+ FREE(sp);
131
+ }
132
+
133
+ base_spline<S>& operator[](int i) {return *base[i];}
134
+
135
+ int Grid() {return N;}
136
+
137
+ Int Kset(const poly<S>& x) const
138
+ {
139
+ int v[N];
140
+ for (int i = 0; i < N; i++) v[i] = base[i]->Kset(x[i]);
141
+ return Int(N, v, 0);
142
+ }
143
+
144
+ private:
145
+
146
+ Int Imax(int as = 1) const
147
+ {
148
+ int v[N];
149
+ for (int i = 0; i < N; i++) v[i] = base[i]->Imax();
150
+ return Int(N, v, as);
151
+ }
152
+ Int Icox(int as = 1) const
153
+ {
154
+ int v[N];
155
+ for (int i = 0; i < N; i++) v[i] = base[i]->Icox();
156
+ return Int(N, v, as);
157
+ }
158
+ Int Rank() const
159
+ {
160
+ int v[N];
161
+ for (int i = 0; i < N; i++) v[i] = base[i]->Rank();
162
+ return Int(N, v, 1);
163
+ }
164
+ Int Jisu() const
165
+ {
166
+ int v[N];
167
+ for (int i = 0; i < N; i++) v[i] = base[i]->Jisu();
168
+ return Int(N, v, 0);
169
+ }
170
+ Int Shuki() const
171
+ {
172
+ int v[N];
173
+ for (int i = 0; i < N; i++) v[i] = base[i]->Shuki();
174
+ return Int(N, v, 0);
175
+ }
176
+ size_t *Maxq() const
177
+ {
178
+ size_t *vp = new size_t[N];
179
+ for (int i = 0; i < N; i++) vp[i] = base[i]->Maxq();
180
+ return vp;
181
+ }
182
+ // end poly_spline
183
+ };
184
+
185
+ /*******************************************************************************
186
+ N変数K次元パラメトリック & リーゼンフェルト スプライン補間
187
+ int N : number of parameters (Grid)
188
+ typename S : poly<S,N> = (s, t, u, ...)
189
+ int K : number of axis (Atom)
190
+ typename T : poly<T,K> = (x, y, z, ...)
191
+ --------------------------------------------------------------------------------
192
+ パラメトリックスプライン (曲面補間) s = {0,...}
193
+ パラメトリック周期スプライン (閉曲面補間)s = {1,...}
194
+ リーゼンフェルトスプライン (曲面補間) s = {2,...}
195
+ リーゼンフェルト周期スプライン(閉曲面補間)s = {3,...}
196
+ *******************************************************************************/
197
+ template <typename T, typename S = double>
198
+ class pspline : public poly_spline<S>
199
+ {
200
+
201
+ int K; T *clp;
202
+
203
+ public:
204
+ // constructor
205
+ pspline():clp(NULL){}
206
+ pspline(const poly_array<T>&, const comb_array<S>&, const Int&, const Int&);
207
+ pspline(const pspline&);
208
+ // destructor
209
+ ~pspline() { delete[] clp; }
210
+ // operator
211
+ pspline& operator=(const pspline&);
212
+ poly_array<T> operator[](const poly<S>& p) const {return (*this)(p);}
213
+ poly_array<T> operator()(const poly<S>&, const int* = NULL) const;
214
+ poly_array<T> operator()(const poly<S>&, int, T*) const;
215
+ poly_array<T> sekibun(const poly<S>&) const;
216
+ int Unit_size() const {return K;}
217
+ operator T* () const {return clp;}
218
+ };
219
+
220
+ template <typename T, typename S>
221
+ pspline<T,S>::pspline(const poly_array<T>& p, const comb_array<S>& x, const Int& j, const Int& s)
222
+ : poly_spline<S>(x, Int(p), j, s), K(p.unit_size())
223
+ {
224
+ Int a = poly_spline<S>::values->imax;
225
+ Int c = poly_spline<S>::values->icox;
226
+ T *alp = clp = new T[c.data_size()];
227
+ poly_view<T> alv(alp, a), clv(clp, c);
228
+ if (s < 2) {
229
+ marray<S> bd = poly_spline<S>::gyoretu(a, x);
230
+ marray_lu_view<S> lu(bd);
231
+ lu.solve((T*)p, alp, K);
232
+ } else
233
+ memcpy(alp, (T*)p, p.data_size() * sizeof(T));
234
+ clv = alv;
235
+ }
236
+ // copy constructor
237
+ template <typename T, typename S>
238
+ pspline<T,S>::pspline(const pspline& ps) : poly_spline<S>(ps), K(ps.K)
239
+ {
240
+ Int c = poly_spline<S>::icox;
241
+ int len = c.data_size();
242
+ clp = new T[len];
243
+ memcpy(clp, (T*)ps, len * sizeof(T));
244
+ }
245
+ // substitution operator
246
+ template <typename T, typename S>
247
+ pspline<T,S>& pspline<T,S>::operator=(const pspline& ps)
248
+ {
249
+ if (this != &ps) {
250
+ delete clp;
251
+ poly_spline<S>::operator=(ps); K = ps.K;
252
+ Int c = poly_spline<S>::icox;
253
+ int len = c.data_size();
254
+ clp = new T[len];
255
+ memcpy(clp, (T*)ps, len * sizeof(T));
256
+ }
257
+ return *this;
258
+ }
259
+
260
+ template <typename T, typename S>
261
+ poly_array<T> pspline<T,S>::operator()(const poly<S>& t, const int *jb) const
262
+ {
263
+ if (jb) {
264
+ Int jbn(t.grid(), jb, 0);
265
+ if (!(poly_spline<S>::values->jisu >= jbn))
266
+ throw "out of range, pspline()";
267
+ }
268
+ T result[K]; for (int i = 0; i < K; ++i) result[i] = 0;
269
+ poly_view<T> res(result, K);
270
+ comp_array<S> pc = poly_spline<S>::basis(t, jb);
271
+ Int& c = poly_spline<S>::values->icox;
272
+ poly_view<T> clv(clp, c);
273
+ Int offset = pc.offset(), size = pc.size();
274
+ int s = size.grid_size();
275
+ for (int i = 0; i < s; ++i)
276
+ {
277
+ Int k = i % size, l = k + offset;
278
+ res += clv[l] * pc[k = 1][0];
279
+ }
280
+ return poly_array<T>(result, K);
281
+ }
282
+
283
+ template <typename T, typename S>
284
+ poly_array<T> pspline<T,S>::operator()(const poly<S>& t, int jbn, T *ds) const
285
+ {
286
+ if (!(poly_spline<S>::values->jisu >= jbn))
287
+ throw "out of range, pspline()";
288
+ T result[K]; for (int i = 0; i < K; ++i) result[i] = 0;
289
+ poly_view<T> res(result, K);
290
+ comp_array<S> pc = poly_spline<S>::bases(t, jbn);
291
+ Int& c = poly_spline<S>::values->icox;
292
+ poly_view<T> clv(clp, c);
293
+ Int offset = pc.offset(), size = pc.size();
294
+ int s = size.grid_size();
295
+ for (int i = 0; i < s; ++i)
296
+ {
297
+ Int k = i % size, l = k + offset;
298
+ res += clv[l] * pc[k = jbn + 1][ds];
299
+ }
300
+ return poly_array<T>(result, K);
301
+ }
302
+
303
+ template <typename T, typename S>
304
+ poly_array<T> pspline<T,S>::sekibun(const poly<S>& t) const
305
+ {
306
+ const Int& c = poly_spline<S>::values->icox;
307
+ const Int& j = poly_spline<S>::values->jisu;
308
+ Int n = poly_spline<S>::Kset(t) - j + 1;
309
+ int Imax = n.grid_size();
310
+ poly_view<T> clw(clp, c);
311
+ int a = c.unit_size();
312
+ T result[a]; for (int i = 0; i < a; i++) result[i] = 0;
313
+ poly_view<T> R(result, a);
314
+ for (int i = 0; i < Imax; ++i) {
315
+ Int h = i % n + j;
316
+ poly_spline<S>::sekibun(R, clw, h, t);
317
+ }
318
+ return poly_array<T>(result, a);
319
+ }
320
+
321
+ // 1変数N次元パラメトリックスプライン
322
+ typedef pspline<double,double> Pspline;
323
+ // 1変数N次元パラメトリックスプライン
324
+ typedef pspline<double,double> Pspline2;
325
+
326
+ /*******************************************************************************
327
+ 1変数多次元パラメトリックスプライン
328
+ *******************************************************************************/
329
+ template <class T = double, class S = T> class bspline : public base_spline<S>
330
+ {
331
+ int K; T *clp;
332
+
333
+ public:
334
+ // constructor
335
+ bspline(const poly_array<T>&, int, S*, int, int = 0, int* = NULL);
336
+ bspline(const bspline&);
337
+ // destructor
338
+ ~bspline() { delete clp; }
339
+ // operator
340
+ bspline& operator=(const bspline&);
341
+ poly_array<T> operator[](S t) const {return (*this)(t);}
342
+ poly_array<T> operator()(S, int = 0) const;
343
+ poly_array<T> sekibun(S) const;
344
+ T line_element(S) const;
345
+ bspline *line_integral(T(*)(poly_array<S>&), int, S*, S = 0, T = 0) const;
346
+ int Unit_size() const {return K;}
347
+ operator T* () const {return clp;}
348
+ };
349
+ /*******************************************************************************
350
+ 1変数パラメトリックスプライン コンストラクタ
351
+ --------------------------------------------------------------------------------
352
+ パラメトリックスプライン (曲線補間) s = 0
353
+ パラメトリック周期スプライン (閉曲線補間)s = 1
354
+ リーゼンフェルトスプライン (曲線補間) s = 2
355
+ リーゼンフェルト周期スプライン(閉曲線補間)s = 3
356
+ *******************************************************************************/
357
+ template <class T, class S>
358
+ bspline<T,S>::bspline(
359
+ const poly_array<T>& p, // Vector Array<1>, [P0,...,Pn-1];
360
+ int n, S* x, // Variables, [X0,...,Xn-1];
361
+ int j, // Dimension
362
+ int s, // Type parameter
363
+ int *d // Differential rank, [D0,...,Dn-1];
364
+ )
365
+ : base_spline<S>(n, x, j, p(0) - n - (s%2)), K(p.unit_size())
366
+ {
367
+ int a = base_spline<S>::imax;
368
+ int c = base_spline<S>::icox;
369
+ T *alp = clp = new T[c * K];
370
+ if (s < 2) {
371
+ marray<S> bd(a, a);
372
+ base_spline<S>::gyoretu((S**)bd, a, x, d); //係数行列を作成
373
+ marray_lu_view<S> lu(bd);
374
+ lu.solve((T*)p, alp, K);
375
+ } else
376
+ memcpy(alp, (T*)p, a * K * sizeof(T));
377
+ poly_view<T> alv(alp, Colon, a, K);
378
+ poly_view<T> clv(clp, Colon, c, K);
379
+ clv = alv;
380
+ }
381
+
382
+ template <class T, class S>
383
+ bspline<T,S>::bspline(const bspline& s) : base_spline<S>(s)
384
+ {
385
+ int c = base_spline<S>::icox;
386
+ clp = new T[c];
387
+ memcpy(clp, s, c * sizeof(T));
388
+ }
389
+
390
+ template <class T, class S>
391
+ bspline<T,S>& bspline<T,S>::operator=(const bspline& s)
392
+ {
393
+ if (this != &s) {
394
+ base_spline<S>::operator=(s);
395
+ delete clp;
396
+ int c = base_spline<S>::icox;
397
+ clp = new T[c];
398
+ memcpy(clp, s, c * sizeof(T));
399
+ }
400
+ return *this;
401
+ }
402
+
403
+ template <typename T, typename S>
404
+ void sekibun(const bspline<T,S>& p, S t, const poly_view<T>& alp, int Jsk, poly_view<T>& sek)
405
+ {
406
+ const base_spline<S>& base = p;
407
+ const Int& size = alp;
408
+ int ks, kset, k = base.Rank() + Jsk;
409
+ S b[k], *q = base.Knots();
410
+ ks = deboor<S>(base.Rank(), q, base.Icox(), t, b, kset, k);
411
+ poly_view<T> *a[2], *w = new poly_view<T>[2*(kset+1)];
412
+ a[0] = w; a[1] = &w[kset+1];
413
+ for (int i = 0; i <= kset; ++i) {
414
+ Int k = i % size;
415
+ a[Jsk%2][i] = alp[k]; a[(Jsk+1)%2][i] = sek;
416
+ }
417
+ while (Jsk) {
418
+ poly_view<T> *a0 = a[Jsk%2], *a1 = a[(Jsk+1)%2];
419
+ for (int i = 0; i <= kset; ++i) {
420
+ if (i == 0) a1[i] = 0.0;
421
+ else a1[i] = a1[i-1];
422
+ a1[i] += a0[i] * ((q[i+(k-Jsk)] - q[i]) / S(k-Jsk));
423
+ }
424
+ Jsk--;
425
+ }
426
+ for (int i = ks > 0 ? ks : 0; i <= kset; ++i)
427
+ sek += a[0][i] * b[i-ks];
428
+ delete[] w;
429
+ }
430
+
431
+ //
432
+ // 1変数パラメトリックスプライン関数値の計算(曲線補間)
433
+ //
434
+
435
+ template <class T, class S>
436
+ poly_array<T> bspline<T,S>::operator()(S t, int b) const
437
+ {
438
+ if (b > base_spline<S>::jisu)
439
+ throw "out of range, bspline value";
440
+ T result[K]; for (int i = 0; i < K; ++i) result[i] = 0;
441
+ poly_view<T> res(result, size_t(K));
442
+ Int c(Colon, base_spline<S>::icox, K);
443
+ poly_view<T> clv(clp, c);
444
+ if (b >= 0) {
445
+ parray<S> bc = base_spline<S>::basis(t, b);
446
+ Int offset(1, bc(0), 0), size(1, bc(1), 0);
447
+ int s = size.grid_size();
448
+ for (int i = 0; i < s; ++i)
449
+ {
450
+ Int k = i % size, l = k + offset;
451
+ res += clv[l] * bc[0][i];
452
+ }
453
+ } else ::sekibun<T,S>(*this, t, clv, -b, res);
454
+ return poly_array<T>(result, K);
455
+ }
456
+
457
+ template <class T, class S>
458
+ poly_array<T> bspline<T,S>::sekibun(S t) const
459
+ {
460
+ T result[K]; for (int i = 0; i < K; ++i) result[i] = 0.0;
461
+ base_spline<S>::sekibun(t, clp, K, result);
462
+ return poly_array<T>(result, K);
463
+ }
464
+
465
+ template <class T, class S>
466
+ T bspline<T,S>::line_element(S t) const
467
+ {
468
+ poly_array<T> r = (*this)(t, 1);
469
+ T s = 0;
470
+ for (int i = 0; i < K; ++i) s += r[i] * r[i];
471
+ return sqrt(s);
472
+ }
473
+
474
+ template <class T, class S>
475
+ bspline<T,S> *bspline<T,S>::line_integral(T(*F)(poly_array<S>&), int n, S *u, S x, T y) const
476
+ {
477
+ int N = n+1, D[N]; S X[N]; T Y[N];
478
+ for (int i = 0; i < n; i++) D[i] = 1; D[n] = 0;
479
+ for (int i = 0; i < n; i++) {
480
+ poly_array<S> U = (*this)[u[i]];
481
+ X[i] = u[i];
482
+ Y[i] = F(U) * this->line_element(u[i]);
483
+ } X[n] = x;
484
+ Y[n] = y;
485
+ poly_array<T> Ya(Y, 1, N, 1);
486
+ return new bspline<T,S>(Ya, n, X, base_spline<S>::jisu, 0, D);
487
+ }
488
+ //
489
+ // misc
490
+ //
491
+ template <class T, class S = double>
492
+ int plot(const pspline<T,S>&, const comb_array<S>&, S**, T**, int, const int* = NULL);
493
+
494
+ template <class T, class S = double>
495
+ int plot(const pspline<T,S>&, const comb_array<S>&, S**, T**, int, int, S*);
496
+
497
+ template <class T, class S = double>
498
+ int plot(const pspline<T,S>&, int, S*, S**, T**, int, int = 0);
499
+
500
+ template <class T, class S = double>
501
+ int plot(const bspline<T,S>&, const comb_array<S>&, S**, T**, int, int = 0);
502
+
503
+ template <class T, class S = double>
504
+ int plot(const bspline<T,S>&, int, S*, S**, T**, int, int = 0);
505
+
506
+ #endif