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,897 @@
1
+ /* Extention for ruby */
2
+
3
+ #include "ruby.h"
4
+
5
+ #ifdef __cplusplus
6
+ # define VALUEFUNC(f) ((VALUE (*)(...))f)
7
+ # define VOIDFUNC(f) ((void (*)(...))f)
8
+ #else
9
+ # define VALUEFUNC(f) (f)
10
+ # define VOIDFUNC(f) (f)
11
+ #endif
12
+
13
+ static VALUE
14
+ _wrap_ary_flatten(VALUE arg)
15
+ {
16
+ VALUE result = rb_ary_new();
17
+ if (TYPE(arg) == T_ARRAY) {
18
+ if(RARRAY_LEN(arg) == 0)
19
+ return result;
20
+ else {
21
+ VALUE last = rb_ary_pop(arg);
22
+ return rb_ary_concat(_wrap_ary_flatten(arg), _wrap_ary_flatten(last));
23
+ }
24
+ } else
25
+ return rb_ary_push(result, arg);
26
+ }
27
+
28
+ #include "bspline.h"
29
+
30
+ static VALUE mPspline;
31
+
32
+ static VALUE cBspline;
33
+
34
+ static void Wrap_free_bspline(bspline<double> *arg0) { delete arg0; }
35
+
36
+ #define Wrap_bspline(klass, ptr) (\
37
+ (ptr) ? Data_Wrap_Struct(klass, 0, VOIDFUNC(Wrap_free_bspline), ptr) : Qnil )
38
+
39
+ #define Get_bspline(val, ptr) {\
40
+ if (NIL_P(val)) ptr = NULL;\
41
+ else {\
42
+ if (!rb_obj_is_kind_of(val, cBspline))\
43
+ rb_raise(rb_eTypeError, "wrong argument type (expected bspline)");\
44
+ Data_Get_Struct(val, bspline<double>, ptr);\
45
+ if (!ptr) rb_raise(rb_eRuntimeError, "This bspline already released");\
46
+ }\
47
+ }
48
+
49
+ // bspline#new()
50
+
51
+ static VALUE
52
+ _wrap_new_bspline(int argc, VALUE *argv, VALUE klass)
53
+ {
54
+ VALUE self = Data_Wrap_Struct(klass, 0, VOIDFUNC(Wrap_free_bspline), 0);
55
+ rb_obj_call_init(self, argc, argv);
56
+ return self;
57
+ }
58
+ /*******************************************************************************
59
+ Calculate interpolation of 1 variable M dimension B-spline.
60
+ bspline.new([...,[Xi,Yi0,...,YiM-1],...], N, J, S)
61
+ X0,..,Xi,..,XN-1:点のX座標
62
+ Yi0, ..., YiM-1:点のY座標
63
+ J:スプライン次数(階数K=J+1)
64
+ Result:B-spline object
65
+ *******************************************************************************/
66
+
67
+ // bspline#initialize
68
+
69
+ static VALUE
70
+ _wrap_init_bspline(int argc, VALUE *argv, VALUE self)
71
+ {
72
+ VALUE va, varg, vargn, vargj, vargs, vargd = Qnil;
73
+ int argp, argn, argj, args = 0, k = 1;
74
+ int *argd = NULL;
75
+ double *x, *y;
76
+
77
+ rb_scan_args(argc, argv, "31", &varg, &vargn, &vargj, &vargs);
78
+
79
+ Check_Type(varg, T_ARRAY);
80
+ argp = RARRAY_LEN(varg);
81
+ argn = NUM2INT(vargn);
82
+ argj = NUM2INT(vargj);
83
+ int D = argp - argn;
84
+ if (D < 0)
85
+ rb_raise(rb_eArgError, "Data points %d < Data size %d", argp, argn);
86
+ if (D >= argj)
87
+ rb_raise(rb_eArgError, "Additional points %d >= Degree %d", D, argj);
88
+ if (argn <= argj)
89
+ rb_raise(rb_eArgError, "Data points %d <= Degree %d", argn, argj);
90
+ if (argc > 3) {
91
+ vargd = argv[3];
92
+ if (TYPE(vargd) == T_ARRAY) {
93
+ int d = RARRAY_LEN(vargd);
94
+ if (d != D)
95
+ rb_raise(rb_eArgError, "Differential orders = %d, it should be %d", d, D);
96
+ argd = ALLOC_N(int, argn + D);
97
+ for (int i = 0; i < argn; ++i)
98
+ argd[i] = 0;
99
+ for (int i = 0; i < D; ++i)
100
+ argd[argn + i] = NUM2INT(RARRAY_PTR(vargd)[i]);
101
+ } else
102
+ args = NUM2INT(vargs);
103
+ }
104
+ va = RARRAY_PTR(varg)[0];
105
+ Check_Type(va, T_ARRAY);
106
+ k = RARRAY_LEN(va) - 1;
107
+ x = ALLOC_N(double, argp);
108
+ y = ALLOC_N(double, argp * k);
109
+ for (int i = 0; i < argp; i++) {
110
+ if (i > 0) {
111
+ va = RARRAY_PTR(varg)[i];
112
+ Check_Type(va, T_ARRAY);
113
+ if (RARRAY_LEN(va) - 1 != k)
114
+ rb_raise(rb_eArgError, "Dimension should be %d", k);
115
+ }
116
+ for (int j = 0; j <= k; ++j)
117
+ if (j == 0) x[i] = NUM2DBL(RARRAY_PTR(va)[0]);
118
+ else y[i*k+j-1] = NUM2DBL(RARRAY_PTR(va)[j]);
119
+ }
120
+ try {
121
+ Int s(Colon, argp - args%2, k);
122
+ poly_array<double> argy(y, s);
123
+ // printf("n = %d, j = %d, s = %d\n", argn, argj, args);
124
+ // argy.print("\n");
125
+ DATA_PTR(self) = new bspline<double>(argy, argn + args%2, x, argj, args, argd);
126
+ } catch (const char *c) {
127
+ rb_raise(rb_eRuntimeError, "%s", c);
128
+ }
129
+ free(y);
130
+ free(x);
131
+ if (argd) free(argd);
132
+ return self;
133
+ }
134
+
135
+ static VALUE
136
+ make_list(int argc, VALUE *argv)
137
+ {
138
+ VALUE vargs = rb_ary_new();
139
+ for (int i = 0; i < argc; i++) {
140
+ if (TYPE(argv[i]) == T_ARRAY) {
141
+ VALUE val = rb_obj_dup(argv[i]);
142
+ vargs = rb_ary_concat(vargs, _wrap_ary_flatten(val));
143
+ }
144
+ else
145
+ rb_ary_push(vargs, argv[i]);
146
+ }
147
+ return vargs;
148
+ }
149
+ /*******************************************************************************
150
+ 関数値
151
+
152
+ bspline#[x[, ...]]
153
+ x:点のX座標(数値,または数値の配列)
154
+
155
+ Result:補間値
156
+ *******************************************************************************/
157
+ static VALUE
158
+ _wrap_bspline_bracket(int argc, VALUE *argv, VALUE self)
159
+ {
160
+ bspline<double> *bsp;
161
+ double arg;
162
+ VALUE val, vargs;
163
+ VALUE vresult = Qnil;
164
+
165
+ Get_bspline(self, bsp);
166
+ int K = bsp->Unit_size();
167
+
168
+ vargs = make_list(argc, argv);
169
+ argc = RARRAY_LEN(vargs);
170
+ try {
171
+ vresult = rb_ary_new();
172
+ for (int i = 0; i < argc; i++) {
173
+ arg = NUM2DBL(RARRAY_PTR(vargs)[i]);
174
+ poly_array<double> result = (*bsp)[arg];
175
+ if (K == 1)
176
+ val = rb_float_new(result[0]);
177
+ else {
178
+ val = rb_ary_new();
179
+ for (int j = 0; j < K; ++j)
180
+ rb_ary_push(val, rb_float_new(result[j]));
181
+ }
182
+ rb_ary_push(vresult, val);
183
+ }
184
+ } catch (const char *c) {
185
+ rb_raise(rb_eRuntimeError, "%s", c);
186
+ }
187
+ return argc == 1 ? rb_ary_shift(vresult) : vresult;
188
+ }
189
+ /*******************************************************************************
190
+ 関数値
191
+ bspline#value(x, d = 0)
192
+ x:点のX座標
193
+ d:微分階数(省略可)
194
+ Result:補間値,または微分値
195
+ *******************************************************************************/
196
+ static VALUE
197
+ _wrap_bspline_value(int argc, VALUE *argv, VALUE self)
198
+ {
199
+ VALUE varg1, varg2 ;
200
+ bspline<double> *arg0 ;
201
+ double arg1 ;
202
+ int arg2 = 0 ;
203
+ VALUE vresult = Qnil;
204
+
205
+ rb_scan_args(argc, argv, "11", &varg1, &varg2);
206
+ Get_bspline(self, arg0);
207
+ int K = arg0->Unit_size();
208
+ arg1 = NUM2DBL(varg1);
209
+ if (argc > 1) arg2 = NUM2INT(varg2);
210
+ try {
211
+ poly_array<double> result = (*arg0)(arg1, arg2);
212
+ if (K == 1)
213
+ vresult = rb_float_new(result[0]);
214
+ else {
215
+ vresult = rb_ary_new();
216
+ for (int j = 0; j < K; ++j)
217
+ rb_ary_push(vresult, rb_float_new(result[j]));
218
+ }
219
+ } catch (const char *c) {
220
+ rb_raise(rb_eRuntimeError, "%s", c);
221
+ }
222
+ return vresult;
223
+ }
224
+
225
+ static VALUE
226
+ _wrap_bspline_sekibun(VALUE self, VALUE varg)
227
+ {
228
+ bspline<double> *arg0 ;
229
+ VALUE vresult = Qnil;
230
+
231
+ Get_bspline(self, arg0);
232
+ int K = arg0->Unit_size();
233
+ try {
234
+ poly_array<double> result = arg0->sekibun(NUM2DBL(varg));
235
+ if (K == 1)
236
+ vresult = rb_float_new(result[0]);
237
+ else {
238
+ vresult = rb_ary_new();
239
+ for (int j = 0; j < K; ++j)
240
+ rb_ary_push(vresult, rb_float_new(result[j]));
241
+ }
242
+ } catch (const char *c) {
243
+ rb_raise(rb_eRuntimeError, "%s", c);
244
+ }
245
+ return vresult;
246
+ }
247
+
248
+ static VALUE
249
+ _wrap_bspline_plot(int argc, VALUE *argv, VALUE self)
250
+ {
251
+ bspline<double> *arg0; // bspline object
252
+ VALUE varg1; // list of point
253
+ VALUE varg3; int arg3; // number of division
254
+ VALUE varg4; int arg4 = 0; // order differential
255
+ rb_scan_args(argc, argv, "21", &varg1, &varg3, &varg4);
256
+ Check_Type(varg1, T_ARRAY);
257
+ arg3 = NUM2INT(varg3);
258
+ if (argc > 2) arg4 = NUM2INT(varg4);
259
+ Get_bspline(self, arg0);
260
+ int argn = RARRAY_LEN(varg1);
261
+ double *argx = ALLOC_N(double, argn);
262
+ for (int i = 0; i < argn; ++i) {
263
+ VALUE x = rb_ary_shift(varg1);
264
+ argx[i] = NUM2DBL(x);
265
+ }
266
+ int K = arg0->Unit_size();
267
+ double *arg1, *arg2[K];
268
+ int result;
269
+ try {
270
+ result = plot<double>(*arg0, argn, argx, &arg1, arg2, arg3, arg4);
271
+ } catch (const char *c) {
272
+ rb_raise(rb_eRuntimeError, "%s", c);
273
+ }
274
+ for (int i = 0; i < result; i++) {
275
+ VALUE v1 = rb_float_new(arg1[i]);
276
+ VALUE v2 = rb_ary_new();
277
+ for (int k = 0; k < K; ++k)
278
+ rb_ary_push(v2, rb_float_new(arg2[k][i]));
279
+ VALUE vv = rb_ary_new();
280
+ rb_ary_push(vv, v1);
281
+ rb_ary_push(vv, v2);
282
+ rb_ary_push(varg1, vv);
283
+ if (rb_block_given_p()) rb_yield(vv);
284
+ }
285
+ free(arg1);
286
+ for (int i = 0; i < K; ++i) free(arg2[i]);
287
+ free(argx);
288
+ return INT2NUM(result);
289
+ }
290
+
291
+ static VALUE
292
+ _wrap_complex_trans(VALUE self, VALUE varg1, VALUE varg2)
293
+ {
294
+ VALUE varg, vargx, vargy, vresult = Qnil;
295
+ Check_Type(varg1, T_ARRAY);
296
+ int argn = RARRAY_LEN(varg1);
297
+ int argf = NUM2INT(varg2);
298
+ if (argf != 1) {
299
+ if (argn != 2) rb_raise(rb_eArgError, "Argument is not Complex");
300
+ vargx = RARRAY_PTR(varg1)[0]; Check_Type(vargx, T_ARRAY);
301
+ vargy = RARRAY_PTR(varg1)[1]; Check_Type(vargy, T_ARRAY);
302
+ argn = RARRAY_LEN(vargx);
303
+ if (argn != RARRAY_LEN(vargy)) rb_raise(rb_eArgError, "Argument is not Complex");
304
+ }
305
+ double *dfft = ALLOC_N(double, argn << 1);
306
+ double *data = ALLOC_N(double, argn << 1);
307
+ if (argf == 1) {
308
+ for (int i = 0; i < argn; i++) {
309
+ varg = RARRAY_PTR(varg1)[i];
310
+ Check_Type(varg, T_ARRAY);
311
+ if (RARRAY_LEN(varg) != 2) rb_raise(rb_eArgError, "Argument is not Complex");
312
+ dfft[2*i] = NUM2DBL(RARRAY_PTR(varg)[0]);
313
+ dfft[2*i+1] = NUM2DBL(RARRAY_PTR(varg)[1]);
314
+ }
315
+ try {
316
+ fft<>::complex_transform(dfft, argn, argf);
317
+ fft<>::half_en_pack(data, argn, dfft);
318
+ } catch (const char *c) {
319
+ rb_raise(rb_eRuntimeError, "%s", c);
320
+ }
321
+ vresult = rb_ary_new();
322
+ vargx = rb_ary_new();
323
+ vargy = rb_ary_new();
324
+ rb_ary_push(vresult, vargx);
325
+ rb_ary_push(vresult, vargy);
326
+ for (int i = 0; i < argn; i++) {
327
+ rb_ary_push(vargx, rb_float_new(data[i]));
328
+ rb_ary_push(vargy, rb_float_new(data[i+argn]));
329
+ }
330
+ } else {
331
+ for (int i = 0; i < argn; i++) {
332
+ data[i] = NUM2DBL(RARRAY_PTR(vargx)[i]);
333
+ data[i+argn] = NUM2DBL(RARRAY_PTR(vargy)[i]);
334
+ }
335
+ try {
336
+ fft<>::half_de_pack(dfft, argn, data);
337
+ fft<>::complex_transform(dfft, argn, argf);
338
+ } catch (const char *c) {
339
+ rb_raise(rb_eRuntimeError, "%s", c);
340
+ }
341
+ vresult = rb_ary_new();
342
+ for (int i = 0; i < argn; i++) {
343
+ varg = rb_ary_new();
344
+ rb_ary_push(vresult, varg);
345
+ rb_ary_push(varg, rb_float_new(dfft[2*i]));
346
+ rb_ary_push(varg, rb_float_new(dfft[2*i+1]));
347
+ }
348
+ }
349
+ free(data);
350
+ free(dfft);
351
+ return vresult;
352
+ }
353
+
354
+ static VALUE
355
+ _wrap_complex_get(VALUE self, VALUE varg1, VALUE varg2)
356
+ {
357
+ VALUE vargx, vargy, vresult = Qnil;
358
+ Check_Type(varg1, T_ARRAY);
359
+ int argn = RARRAY_LEN(varg1);
360
+ int args = NUM2INT(varg2);
361
+ if (argn != 2) rb_raise(rb_eArgError, "Argument is not Complex");
362
+ vargx = RARRAY_PTR(varg1)[0];
363
+ vargy = RARRAY_PTR(varg1)[1];
364
+ argn = RARRAY_LEN(vargx);
365
+ if (RARRAY_LEN(vargy) != argn) rb_raise(rb_eArgError, "Argument is not Complex");
366
+ double *data = ALLOC_N(double, argn << 1);
367
+ for (int i = 0; i < argn; i++) {
368
+ data[i] = NUM2DBL(RARRAY_PTR(vargx)[i]);
369
+ data[i+argn] =NUM2DBL(RARRAY_PTR(vargy)[i]);
370
+ }
371
+ double w[2];
372
+ fft<>::half_get(data, argn, args, w);
373
+ vresult = rb_ary_new();
374
+ rb_ary_push(vresult, rb_float_new(w[0]));
375
+ rb_ary_push(vresult, rb_float_new(w[1]));
376
+ free(data);
377
+ return vresult;
378
+ }
379
+
380
+ static VALUE
381
+ _wrap_real_trans(VALUE self, VALUE varg1, VALUE varg2)
382
+ {
383
+ VALUE vresult = Qnil;
384
+ Check_Type(varg1, T_ARRAY);
385
+ int argn = RARRAY_LEN(varg1);
386
+ int argf = NUM2INT(varg2);
387
+ double *data = ALLOC_N(double, argn);
388
+ for (int i = 0; i < argn; i++)
389
+ data[i] = NUM2DBL(RARRAY_PTR(varg1)[i]);
390
+ try {
391
+ fft<>::real_transform(data, argn, argf);
392
+ } catch (const char *c) {
393
+ rb_raise(rb_eRuntimeError, "%s", c);
394
+ }
395
+ vresult = rb_ary_new();
396
+ for (int i = 0; i < argn; i++)
397
+ rb_ary_push(vresult, rb_float_new(data[i]));
398
+ free(data);
399
+ return vresult;
400
+ }
401
+
402
+ static VALUE
403
+ _wrap_real_get(VALUE self, VALUE varg1, VALUE varg2)
404
+ {
405
+ VALUE vresult = Qnil;
406
+ Check_Type(varg1, T_ARRAY);
407
+ int argn = RARRAY_LEN(varg1);
408
+ int args = NUM2INT(varg2);
409
+ double *data = ALLOC_N(double, argn);
410
+ for (int i = 0; i < argn; i++)
411
+ data[i] = NUM2DBL(RARRAY_PTR(varg1)[i]);
412
+ double w[2];
413
+ fft<>::real_get(data, argn, args, w);
414
+ vresult = rb_ary_new();
415
+ rb_ary_push(vresult, rb_float_new(w[0]));
416
+ rb_ary_push(vresult, rb_float_new(w[1]));
417
+ free(data);
418
+ return vresult;
419
+ }
420
+
421
+ static VALUE
422
+ _wrap_complex_bspline(VALUE self, VALUE varg1, VALUE varg2)
423
+ {
424
+ Check_Type(varg1, T_ARRAY);
425
+ int argn = RARRAY_LEN(varg1);
426
+ if (argn != 2) rb_raise(rb_eArgError, "Argument is not Complex");
427
+ VALUE vargx = RARRAY_PTR(varg1)[0];
428
+ VALUE vargy = RARRAY_PTR(varg1)[1];
429
+ Check_Type(vargx, T_ARRAY);
430
+ Check_Type(vargy, T_ARRAY);
431
+ argn = RARRAY_LEN(vargx);
432
+ if (RARRAY_LEN(vargy) != argn) rb_raise(rb_eArgError, "Argument is not Complex");
433
+ double *data = ALLOC_N(double, argn << 1);
434
+ for (int i = 0; i < argn; i++) {
435
+ data[i] = NUM2DBL(RARRAY_PTR(vargx)[i]);
436
+ data[i+argn] = NUM2DBL(RARRAY_PTR(vargy)[i]);
437
+ }
438
+ double *dfft = ALLOC_N(double, argn << 1);
439
+ fft<>::half_de_pack(dfft, argn, data);
440
+ int argj = NUM2INT(varg2);
441
+ bspline<> *result;
442
+ try {
443
+ result = fft<>::cfft(dfft, argn, argj);
444
+ } catch (const char *c) {
445
+ rb_raise(rb_eRuntimeError, "%s", c);
446
+ }
447
+ if (rb_block_given_p()) {
448
+ double val[2]; int N = argn / 2;
449
+ for (int i = -N; i <= N + argn%2; i++) {
450
+ fft<>::half_get(data, argn, i, val);
451
+ VALUE vv = rb_ary_new();
452
+ rb_ary_push(vv, INT2NUM(i));
453
+ VALUE xy = rb_ary_new();
454
+ rb_ary_push(xy, rb_float_new(val[0]));
455
+ rb_ary_push(xy, rb_float_new(val[1]));
456
+ rb_ary_push(vv, xy);
457
+ rb_yield(vv);
458
+ }
459
+ }
460
+ free(dfft);
461
+ free(data);
462
+ return Wrap_bspline(cBspline, result);
463
+ }
464
+
465
+ static VALUE
466
+ _wrap_real_bspline(VALUE self, VALUE varg1, VALUE varg2)
467
+ {
468
+ Check_Type(varg1, T_ARRAY);
469
+ int argn = RARRAY_LEN(varg1);
470
+ double *data = ALLOC_N(double, argn);
471
+ for (int i = 0; i < argn; i++)
472
+ data[i] = NUM2DBL(RARRAY_PTR(varg1)[i]);
473
+ int argj = NUM2INT(varg2);
474
+ bspline<> *result;
475
+ try {
476
+ result = fft<>::rfft(data, argn, argj);
477
+ } catch (const char *c) {
478
+ rb_raise(rb_eRuntimeError, "%s", c);
479
+ }
480
+ if (rb_block_given_p()) {
481
+ double val[2]; int N = argn / 2;
482
+ for (int i = -N; i <= N + argn%2; i++) {
483
+ fft<>::real_get(data, argn, i, val);
484
+ VALUE vv = rb_ary_new();
485
+ rb_ary_push(vv, INT2NUM(i));
486
+ VALUE xy = rb_ary_new();
487
+ rb_ary_push(vv, xy);
488
+ rb_ary_push(xy, rb_float_new(val[0]));
489
+ rb_ary_push(xy, rb_float_new(val[1]));
490
+ rb_yield(vv);
491
+ }
492
+ }
493
+ free(data);
494
+ return Wrap_bspline(cBspline, result);
495
+ }
496
+
497
+ static void
498
+ _wrap_Init_bspline(void)
499
+ {
500
+ cBspline = rb_define_class_under(mPspline, "Bspline", rb_cObject);
501
+ rb_include_module(cBspline, rb_mEnumerable);
502
+ rb_define_singleton_method(cBspline, "new", VALUEFUNC(_wrap_new_bspline), -1);
503
+ rb_define_method(cBspline, "initialize", VALUEFUNC(_wrap_init_bspline), -1);
504
+ rb_define_method(cBspline, "[]", VALUEFUNC(_wrap_bspline_bracket), -1);
505
+ rb_define_method(cBspline, "value", VALUEFUNC(_wrap_bspline_value), -1);
506
+ rb_define_method(cBspline, "sekibun", VALUEFUNC(_wrap_bspline_sekibun), 1);
507
+ rb_define_method(cBspline, "plot", VALUEFUNC(_wrap_bspline_plot), -1);
508
+ rb_define_module_function(mPspline, "fft_complex_transform", VALUEFUNC(_wrap_complex_trans), 2);
509
+ rb_define_module_function(mPspline, "fft_complex_get", VALUEFUNC(_wrap_complex_get), 2);
510
+ rb_define_module_function(mPspline, "fft_complex_bspline", VALUEFUNC(_wrap_complex_bspline), 2);
511
+ rb_define_module_function(mPspline, "fft_real_transform", VALUEFUNC(_wrap_real_trans), 2);
512
+ rb_define_module_function(mPspline, "fft_real_get", VALUEFUNC(_wrap_real_get), 2);
513
+ rb_define_module_function(mPspline, "fft_real_bspline", VALUEFUNC(_wrap_real_bspline), 2);
514
+ }
515
+
516
+ static VALUE cPspline;
517
+
518
+ static void Wrap_free_pspline(pspline<double> *arg0) { delete arg0; }
519
+
520
+ #define Wrap_pspline(klass, ptr) (\
521
+ (ptr) ? Data_Wrap_Struct(klass, 0, VOIDFUNC(Wrap_free_pspline), ptr) : Qnil )
522
+
523
+ #define Get_pspline(val, ptr) {\
524
+ if (NIL_P(val)) ptr = NULL;\
525
+ else {\
526
+ if (!rb_obj_is_kind_of(val, cPspline))\
527
+ rb_raise(rb_eTypeError, "wrong argument type (expected pspline)");\
528
+ Data_Get_Struct(val, pspline<double>, ptr);\
529
+ if (!ptr) rb_raise(rb_eRuntimeError, "This pspline already released");\
530
+ }\
531
+ }
532
+
533
+ // Pspline#new()
534
+
535
+ static VALUE
536
+ _wrap_new_pspline(int argc, VALUE *argv, VALUE klass)
537
+ {
538
+ VALUE self = Data_Wrap_Struct(klass, 0, VOIDFUNC(Wrap_free_pspline), 0);
539
+ rb_obj_call_init(self, argc, argv);
540
+ return self;
541
+ }
542
+
543
+ #define Get_param(N, varg, ptr, str) {\
544
+ Check_Type(varg, T_ARRAY);\
545
+ int k = RARRAY_LEN(varg);\
546
+ if (k != N)\
547
+ rb_raise(rb_eArgError, "%s list length = %d, it should be %d", str, k, N);\
548
+ ptr = ALLOC_N(int, k);\
549
+ for (int i = 0; i < k; ++i) ptr[i] = NUM2INT(RARRAY_PTR(varg)[i]);\
550
+ }
551
+
552
+ static comb_array<double> make_var(int N, VALUE var, int *n = NULL, int *m = NULL)
553
+ {
554
+ int M = 0, s[N]; VALUE vs[N];
555
+ for (int i = 0; i < N; ++i) {
556
+ vs[i] = RARRAY_PTR(var)[i];
557
+ Check_Type(vs[i], T_ARRAY);
558
+ s[i] = RARRAY_LEN(vs[i]);
559
+ if (n != NULL && m != NULL) {
560
+ int vars = n[i] + m[i]%2;
561
+ if (s[i] != vars)
562
+ rb_raise(rb_eArgError, "Elements = %d, it should be %d", s[i], vars);
563
+ }
564
+ M += s[i];
565
+ }
566
+ double v[M], *p = v;
567
+ for (int i = 0; i < N; ++i)
568
+ for (int j = 0; j < s[i]; ++j)
569
+ *p++ = NUM2DBL(RARRAY_PTR(vs[i])[j]);
570
+ return comb_array<double>(v, N, s, 1);
571
+ }
572
+
573
+ static VALUE make_flat(int K, VALUE val, int N, int *n)
574
+ {
575
+ if (N == 0) return val;
576
+ if (K != n[0]) rb_raise(rb_eArgError, "Wrong argument Array");
577
+ VALUE vals = rb_ary_new();
578
+ for (int i = 0; i < K; ++i) {
579
+ VALUE va = RARRAY_PTR(val)[i];
580
+ if (TYPE(va) == T_ARRAY) {
581
+ VALUE vb = rb_obj_dup(va);
582
+ vals = rb_ary_concat(vals, make_flat(RARRAY_LEN(va), vb, N-1, n+1));
583
+ }
584
+ else
585
+ rb_ary_push(vals, va);
586
+ }
587
+ return vals;
588
+ }
589
+
590
+ static poly_array<double> make_val(int &K, VALUE val, int N, int *n)
591
+ {
592
+ if (K != n[0]) rb_raise(rb_eArgError, "Member size = %d, it should be %d", K, n[0]);
593
+ VALUE vals = rb_ary_new();
594
+ for (int i = 0; i < K; ++i) {
595
+ VALUE va = RARRAY_PTR(val)[i];
596
+ if (TYPE(va) == T_ARRAY) {
597
+ VALUE vb = rb_obj_dup(va);
598
+ vals = rb_ary_concat(vals, make_flat(RARRAY_LEN(va), vb, N-1, n+1));
599
+ }
600
+ else
601
+ rb_ary_push(vals, va);
602
+ }
603
+ int M = RARRAY_LEN(vals);
604
+ K = M;
605
+ for (int i = 0; i < N; ++i) K /= n[i];
606
+ double v[M];
607
+ for (int i = 0; i < M; ++i) v[i] = NUM2DBL(RARRAY_PTR(vals)[i]);
608
+ return poly_array<double>(v, N, n, K);
609
+ }
610
+ /*******************************************************************************
611
+ Calculate interpolation of N variable M dimension P-spline.
612
+ Pspline.new([X^Y^...], [S,T,...], N, J, S)
613
+ X^Y^...:点の座標
614
+ S,T,...:変数の座標
615
+ N:
616
+ J:スプライン次数(階数K=J+1)
617
+ S:
618
+ Result:P-spline object
619
+ *******************************************************************************/
620
+
621
+ // Pspline#initialize
622
+
623
+ static VALUE
624
+ _wrap_init_pspline(int argc, VALUE *argv, VALUE self)
625
+ {
626
+ VALUE vxyz, vstu, vargn, vargj, vargs;
627
+
628
+ int N, K, *n, *j, *s;
629
+
630
+ rb_scan_args(argc, argv, "5", &vxyz, &vstu, &vargn, &vargj, &vargs);
631
+
632
+ Check_Type(vstu, T_ARRAY);
633
+ N = RARRAY_LEN(vstu);
634
+
635
+ Get_param(N, vargs, s, "Type");
636
+
637
+ Get_param(N, vargj, j, "Degree");
638
+
639
+ Get_param(N, vargn, n, "Size");
640
+
641
+ Check_Type(vxyz, T_ARRAY);
642
+ K = RARRAY_LEN(vxyz);
643
+
644
+ try {
645
+
646
+ comb_array<double> stu = make_var(N, vstu, n, s);
647
+ poly_array<double> xyz = make_val(K, vxyz, N, n);
648
+
649
+ Int argn(N, n, K);
650
+ Int argj(N, j, 0);
651
+ Int args(N, s, 0);
652
+ // argn.print(", "); argj.print(", "); args.print("\n");
653
+ // stu.print("\n"); xyz.print("\n");
654
+ DATA_PTR(self) = new pspline<double>(xyz, stu, argj, args);
655
+
656
+ } catch (const char *c) {
657
+ rb_raise(rb_eRuntimeError, "%s", c);
658
+ }
659
+ free(n);
660
+ free(j);
661
+ free(s);
662
+ return self;
663
+ }
664
+ /*******************************************************************************
665
+ 関数値
666
+
667
+ pspline#[x[, ...]]
668
+ x:点のX座標(数値,または数値の配列)
669
+
670
+ Result:補間値
671
+ *******************************************************************************/
672
+ static VALUE
673
+ _wrap_pspline_bracket(int argc, VALUE *argv, VALUE self)
674
+ {
675
+ pspline<double> *bsp;
676
+ VALUE vargs, vresult, mresult = Qnil;
677
+
678
+ Get_pspline(self, bsp);
679
+ int N = bsp->Grid();
680
+ int K = bsp->Unit_size();
681
+
682
+ vargs = make_list(argc, argv);
683
+ argc = RARRAY_LEN(vargs);
684
+ int M = argc / N;
685
+ try {
686
+ if (argc % N == 0) {
687
+ mresult = rb_ary_new();
688
+ for (int m = 0; m < M; ++m) {
689
+ double args[N+1];
690
+ for (int i = 0; i < N; ++i)
691
+ args[i] = NUM2DBL(RARRAY_PTR(vargs)[N*m+i]);
692
+ poly<double> arg(args, N);
693
+ poly_array<double> val = (*bsp)[arg];
694
+ if (K == 1)
695
+ vresult = rb_float_new(val[0]);
696
+ else {
697
+ vresult = rb_ary_new();
698
+ for (int j = 0; j < K; ++j)
699
+ rb_ary_push(vresult, rb_float_new(val[j]));
700
+ }
701
+ rb_ary_push(mresult, vresult);
702
+ }
703
+ } else rb_raise(rb_eArgError, "wrong argument []");
704
+ } catch (const char *c) {
705
+ rb_raise(rb_eRuntimeError, "%s", c);
706
+ }
707
+ return M == 1 ? rb_ary_shift(mresult) : mresult;
708
+ }
709
+ /*******************************************************************************
710
+ 関数値
711
+ pspline#value(x, d = 0)
712
+ x:点のX座標
713
+ d:微分階数(省略可)
714
+ Result:補間値,または微分値
715
+ *******************************************************************************/
716
+ static VALUE
717
+ _wrap_pspline_value(int argc, VALUE *argv, VALUE self)
718
+ {
719
+ VALUE varg1, varg2, varg3;
720
+ pspline<double> *arg0;
721
+ int argn, arg2 = 0, *carg2 = NULL;
722
+ double *carg3 = NULL;
723
+ VALUE vargs, vresult = Qnil;
724
+
725
+ rb_scan_args(argc, argv, "12", &varg1, &varg2, &varg3);
726
+
727
+ Get_pspline(self, arg0);
728
+ int N = arg0->Grid();
729
+ int K = arg0->Unit_size();
730
+ // 全微分
731
+ if (argc == 3) {
732
+ arg2 = NUM2INT(varg2);
733
+ carg3 = new double[N];
734
+ Check_Type(varg3, T_ARRAY);
735
+ for (int i = 0; i < N; ++i)
736
+ carg3[i] = NUM2DBL(RARRAY_PTR(varg3)[i]);
737
+ }
738
+ // 偏微分
739
+ if (argc == 2) {
740
+ carg2 = new int[N];
741
+ Check_Type(varg2, T_ARRAY);
742
+ for (int i = 0; i < N; ++i)
743
+ carg2[i] = NUM2INT(RARRAY_PTR(varg2)[i]);
744
+ }
745
+ // Argument list
746
+ Check_Type(varg1, T_ARRAY);
747
+ argn = RARRAY_LEN(varg1);
748
+ vargs = make_list(argn, RARRAY_PTR(varg1));
749
+ argn = RARRAY_LEN(vargs);
750
+ if (argn == N) {
751
+ double args[N+1];
752
+ for (int i = 0; i < N; ++i)
753
+ args[i] = NUM2DBL(RARRAY_PTR(vargs)[i]);
754
+ poly_array<double> val;
755
+ try {
756
+ poly<double> arg(args, N);
757
+ switch (argc) {
758
+ case 1: // 関数値
759
+ val = (*arg0)(arg);
760
+ break;
761
+ case 2: // 偏微分 (partial derivative)
762
+ val = (*arg0)(arg, carg2);
763
+ delete[] carg2;
764
+ break;
765
+ case 3: // 全微分 (total derivative)
766
+ val = (*arg0)(arg, arg2, carg3);
767
+ delete[] carg3;
768
+ }
769
+ } catch (const char *c) {
770
+ rb_raise(rb_eRuntimeError, "%s", c);
771
+ }
772
+ if (K == 1)
773
+ vresult = rb_float_new(val[0]);
774
+ else {
775
+ vresult = rb_ary_new();
776
+ for (int j = 0; j < K; ++j)
777
+ rb_ary_push(vresult, rb_float_new(val[j]));
778
+ }
779
+ } else rb_raise(rb_eArgError, "wrong argument value");
780
+ return vresult;
781
+ }
782
+
783
+ static VALUE
784
+ _wrap_pspline_sekibun(int argc, VALUE *argv, VALUE self)
785
+ {
786
+ pspline<double> *bsp;
787
+ VALUE vargs, vresult = Qnil;
788
+
789
+ Get_pspline(self, bsp);
790
+ int N = bsp->Grid();
791
+ int K = bsp->Unit_size();
792
+
793
+ vargs = make_list(argc, argv);
794
+ argc = RARRAY_LEN(vargs);
795
+ try {
796
+ if (argc == N) {
797
+ double s[N+1];
798
+ for (int i = 0; i < N; ++i)
799
+ s[i] = NUM2DBL(RARRAY_PTR(vargs)[i]);
800
+ poly<double> args(s, N);
801
+ poly_array<double> val = bsp->sekibun(args);
802
+ if (K == 1)
803
+ vresult = rb_float_new(val[0]);
804
+ else {
805
+ vresult = rb_ary_new();
806
+ for (int j = 0; j < K; ++j)
807
+ rb_ary_push(vresult, rb_float_new(val[j]));
808
+ }
809
+ } else rb_raise(rb_eArgError, "wrong argument Sekibun");
810
+ } catch (const char *c) {
811
+ rb_raise(rb_eRuntimeError, "%s", c);
812
+ }
813
+ return vresult;
814
+ }
815
+
816
+ static VALUE
817
+ _wrap_pspline_plot(int argc, VALUE *argv, VALUE self)
818
+ {
819
+ pspline<double> *arg0;
820
+ VALUE vstu, varg, vdp, vjbn;
821
+ int arg3, *arg4 = NULL;
822
+
823
+ rb_scan_args(argc, argv, "21", &varg, &vdp, &vjbn);
824
+
825
+ Get_pspline(self, arg0);
826
+ int N = arg0->Grid();
827
+ int K = arg0->Unit_size();
828
+ double *arg1[N], *arg2[K];
829
+ arg3 = NUM2INT(vdp);
830
+ if (argc > 2) {
831
+ Check_Type(vjbn, T_ARRAY);
832
+ int n = RARRAY_LEN(vjbn);
833
+ if (n != N)
834
+ rb_raise(rb_eArgError, "Differential orders = %d, it should be %d", n, N);
835
+ arg4 = new int[N];
836
+ for (int i = 0; i < N; ++i)
837
+ arg4[i] = NUM2INT(RARRAY_PTR(vjbn)[i]);
838
+ }
839
+ Check_Type(varg, T_ARRAY);
840
+ N = RARRAY_LEN(varg);
841
+ vstu = rb_ary_new();
842
+ int result;
843
+ for (int i = 0; i < N; ++i) rb_ary_push(vstu, rb_ary_shift(varg));
844
+ try {
845
+ comb_array<double> stu = make_var(N, vstu);
846
+ // printf("dp = %d, jbn = %d\n", arg3, arg4);
847
+ // stu.print("\n");
848
+ result = plot<double>(*arg0, stu, arg1, arg2, arg3, arg4);
849
+ } catch (const char *c) {
850
+ rb_raise(rb_eRuntimeError, "%s", c);
851
+ }
852
+ delete[] arg4;
853
+ for (int i = 0; i < result; i++) {
854
+ VALUE v1 = rb_ary_new();
855
+ for (int j = 0; j < N; ++j) rb_ary_push(v1, rb_float_new(arg1[j][i]));
856
+ VALUE v2 = rb_ary_new();
857
+ for (int k = 0; k < K; ++k) rb_ary_push(v2, rb_float_new(arg2[k][i]));
858
+ VALUE vv = rb_ary_new();
859
+ rb_ary_push(vv, v1);
860
+ rb_ary_push(vv, v2);
861
+ rb_ary_push(varg, vv);
862
+ if (rb_block_given_p()) rb_yield(vv);
863
+ }
864
+ for (int i = 0; i < N; ++i) FREE(arg1[i]);
865
+ for (int i = 0; i < K; ++i) FREE(arg2[i]);
866
+ return INT2NUM(result);
867
+ }
868
+
869
+ static void
870
+ _wrap_Init_pspline(void)
871
+ {
872
+ cPspline = rb_define_class_under(mPspline, "Pspline", rb_cObject);
873
+ rb_include_module(cPspline, rb_mEnumerable);
874
+ rb_define_singleton_method(cPspline, "new", VALUEFUNC(_wrap_new_pspline), -1);
875
+ rb_define_method(cPspline, "initialize", VALUEFUNC(_wrap_init_pspline), -1);
876
+ rb_define_method(cPspline, "[]", VALUEFUNC(_wrap_pspline_bracket), -1);
877
+ rb_define_method(cPspline, "value", VALUEFUNC(_wrap_pspline_value), -1);
878
+ rb_define_method(cPspline, "sekibun", VALUEFUNC(_wrap_pspline_sekibun), -1);
879
+ rb_define_method(cPspline, "plot", VALUEFUNC(_wrap_pspline_plot), -1);
880
+ }
881
+
882
+ #ifdef __cplusplus
883
+ extern "C" {
884
+ #endif
885
+
886
+ void Init_pspline(void)
887
+ {
888
+ mPspline = rb_define_module("PSPLINE");
889
+
890
+ _wrap_Init_bspline();
891
+ _wrap_Init_pspline();
892
+ }
893
+
894
+ #ifdef __cplusplus
895
+ }
896
+ #endif
897
+