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.
- checksums.yaml +4 -4
- data/Gemfile +5 -5
- data/README.md +44 -43
- data/Rakefile +6 -6
- data/bin/console +14 -14
- data/bin/setup +8 -8
- data/ext/pspline/basis.cpp +394 -351
- data/ext/pspline/example/exbspline.rb +57 -57
- data/ext/pspline/example/excspline.rb +57 -57
- data/ext/pspline/example/exdspline.rb +55 -55
- data/ext/pspline/example/exfspline.rb +44 -44
- data/ext/pspline/example/exfspline1.rb +40 -40
- data/ext/pspline/example/exfspline2.rb +68 -68
- data/ext/pspline/example/exfspline3.rb +64 -64
- data/ext/pspline/example/exmspline.rb +68 -68
- data/ext/pspline/example/expspline.rb +29 -29
- data/ext/pspline/example/expspline1.rb +29 -29
- data/ext/pspline/example/expspline2.rb +47 -47
- data/ext/pspline/example/exqspline.rb +31 -31
- data/ext/pspline/example/exqspline1.rb +31 -31
- data/ext/pspline/example/exqspline2.rb +50 -50
- data/ext/pspline/example/exqspline3.rb +51 -51
- data/ext/pspline/example/exqspline4.rb +35 -35
- data/ext/pspline/example/exrspline.rb +34 -34
- data/ext/pspline/example/exrspline1.rb +34 -34
- data/ext/pspline/example/exrspline2.rb +44 -44
- data/ext/pspline/example/exsspline.rb +35 -35
- data/ext/pspline/example/exsspline1.rb +35 -35
- data/ext/pspline/example/extspline.rb +54 -54
- data/ext/pspline/extconf.rb +7 -7
- data/ext/pspline/fft.cpp +27 -552
- data/ext/pspline/include/basis/basis.h +145 -137
- data/ext/pspline/include/basis/fft.h +188 -152
- data/ext/pspline/include/basis/fft_complex.h +215 -0
- data/ext/pspline/include/basis/fft_real.h +625 -0
- data/ext/pspline/include/basis/gabs.h +35 -0
- data/ext/pspline/include/basis/marray_class_ext.h +568 -0
- data/ext/pspline/include/basis/marray_ext.h +100 -0
- data/ext/pspline/include/basis/matrix_luc_ext.h +300 -0
- data/ext/pspline/include/basis/matrix_lud_ext.h +298 -0
- data/ext/pspline/include/basis/poly.h +454 -0
- data/ext/pspline/include/basis/poly_array.h +1030 -1568
- data/ext/pspline/include/basis/pspline.h +806 -642
- data/ext/pspline/include/basis/real.h +526 -0
- data/ext/pspline/include/basis/real_inline.h +442 -0
- data/ext/pspline/include/basis/spline.h +83 -0
- data/ext/pspline/include/basis/uspline.h +251 -210
- data/ext/pspline/include/basis/util.h +122 -656
- data/ext/pspline/include/bspline.h +71 -377
- data/ext/pspline/include/bspline_Config.h +8 -2
- data/ext/pspline/include/real_config.h +3 -0
- data/ext/pspline/pspline.cpp +1236 -1038
- data/ext/pspline/real.cpp +1607 -0
- data/ext/pspline/real_const.cpp +585 -0
- data/lib/pspline.rb +71 -71
- data/lib/pspline/version.rb +1 -1
- data/pspline.gemspec +25 -25
- metadata +17 -5
- data/ext/pspline/plotsub.cpp +0 -139
- data/ext/pspline/util.cpp +0 -483
|
@@ -1,642 +1,806 @@
|
|
|
1
|
-
#ifndef
|
|
2
|
-
#define
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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()
|
|
31
|
-
{
|
|
32
|
-
size_t n = own.Grid();
|
|
33
|
-
knots = new carray_view<S>(n, own.Maxq(), NULL);
|
|
34
|
-
|
|
35
|
-
|
|
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
|
|
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.
|
|
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.
|
|
89
|
-
}
|
|
90
|
-
// destructor
|
|
91
|
-
~poly_spline() {delete[] base; delete values;}
|
|
92
|
-
//
|
|
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.
|
|
102
|
-
}
|
|
103
|
-
return *this;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
base->
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
S
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
{
|
|
248
|
-
|
|
249
|
-
int
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
//
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
}
|
|
306
|
-
//
|
|
307
|
-
template <typename T, typename S>
|
|
308
|
-
|
|
309
|
-
{
|
|
310
|
-
if (
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
Int
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
int
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
for (int i = 0; i <
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
)
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
{
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
int
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
return
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
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
|