pspline 5.0.5 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -5
  3. data/README.md +44 -43
  4. data/Rakefile +6 -6
  5. data/bin/console +14 -14
  6. data/bin/setup +8 -8
  7. data/ext/pspline/basis.cpp +394 -351
  8. data/ext/pspline/example/exbspline.rb +57 -57
  9. data/ext/pspline/example/excspline.rb +57 -57
  10. data/ext/pspline/example/exdspline.rb +55 -55
  11. data/ext/pspline/example/exfspline.rb +44 -44
  12. data/ext/pspline/example/exfspline1.rb +40 -40
  13. data/ext/pspline/example/exfspline2.rb +68 -68
  14. data/ext/pspline/example/exfspline3.rb +64 -64
  15. data/ext/pspline/example/exmspline.rb +68 -68
  16. data/ext/pspline/example/expspline.rb +29 -29
  17. data/ext/pspline/example/expspline1.rb +29 -29
  18. data/ext/pspline/example/expspline2.rb +47 -47
  19. data/ext/pspline/example/exqspline.rb +31 -31
  20. data/ext/pspline/example/exqspline1.rb +31 -31
  21. data/ext/pspline/example/exqspline2.rb +50 -50
  22. data/ext/pspline/example/exqspline3.rb +51 -51
  23. data/ext/pspline/example/exqspline4.rb +35 -35
  24. data/ext/pspline/example/exrspline.rb +34 -34
  25. data/ext/pspline/example/exrspline1.rb +34 -34
  26. data/ext/pspline/example/exrspline2.rb +44 -44
  27. data/ext/pspline/example/exsspline.rb +35 -35
  28. data/ext/pspline/example/exsspline1.rb +35 -35
  29. data/ext/pspline/example/extspline.rb +54 -54
  30. data/ext/pspline/extconf.rb +7 -7
  31. data/ext/pspline/fft.cpp +27 -552
  32. data/ext/pspline/include/basis/basis.h +145 -137
  33. data/ext/pspline/include/basis/fft.h +188 -152
  34. data/ext/pspline/include/basis/fft_complex.h +215 -0
  35. data/ext/pspline/include/basis/fft_real.h +625 -0
  36. data/ext/pspline/include/basis/gabs.h +35 -0
  37. data/ext/pspline/include/basis/marray_class_ext.h +568 -0
  38. data/ext/pspline/include/basis/marray_ext.h +100 -0
  39. data/ext/pspline/include/basis/matrix_luc_ext.h +300 -0
  40. data/ext/pspline/include/basis/matrix_lud_ext.h +298 -0
  41. data/ext/pspline/include/basis/poly.h +454 -0
  42. data/ext/pspline/include/basis/poly_array.h +1030 -1568
  43. data/ext/pspline/include/basis/pspline.h +806 -642
  44. data/ext/pspline/include/basis/real.h +526 -0
  45. data/ext/pspline/include/basis/real_inline.h +442 -0
  46. data/ext/pspline/include/basis/spline.h +83 -0
  47. data/ext/pspline/include/basis/uspline.h +251 -210
  48. data/ext/pspline/include/basis/util.h +122 -656
  49. data/ext/pspline/include/bspline.h +71 -377
  50. data/ext/pspline/include/bspline_Config.h +8 -2
  51. data/ext/pspline/include/real_config.h +3 -0
  52. data/ext/pspline/pspline.cpp +1236 -1038
  53. data/ext/pspline/real.cpp +1607 -0
  54. data/ext/pspline/real_const.cpp +585 -0
  55. data/lib/pspline.rb +71 -71
  56. data/lib/pspline/version.rb +1 -1
  57. data/pspline.gemspec +25 -25
  58. metadata +17 -5
  59. data/ext/pspline/plotsub.cpp +0 -139
  60. data/ext/pspline/util.cpp +0 -483
@@ -0,0 +1,3 @@
1
+ //#define SLOPPY
2
+ #define IEEE
3
+ //#define CROUT
@@ -1,1038 +1,1236 @@
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 VALUE vfunc;
498
-
499
- static double ufunc(poly_array<double>& pa)
500
- {
501
- int K = pa.unit_size();
502
- VALUE *vp = ALLOC_N(VALUE, K);
503
- for (int i = 0; i < K; i++) vp[i] = rb_float_new(pa[i]);
504
- VALUE vresult = rb_funcall2(vfunc, rb_intern("call"), K, vp);
505
- free(vp);
506
- return NUM2DBL(vresult);
507
- }
508
-
509
- static VALUE
510
- _wrap_bspline_lint(int argc, VALUE *argv, VALUE self)
511
- {
512
- bspline<double> *arg0; // bspline object
513
- VALUE vargu, vargx, vargy;
514
- Get_bspline(self, arg0);
515
- rb_scan_args(argc, argv, "22", &vfunc, &vargu, &vargx, &vargy);
516
- int c = arg0->Icox(), j = arg0->Jisu(), n;
517
- double *q = arg0->Knots(), x = arg0->x_min(), y = arg0->x_max();
518
- Check_Type(vargu, T_ARRAY);
519
- int argn = RARRAY_LEN(vargu);
520
- n = argn > 0 ? argn : c - j + 1;
521
- double *u = ALLOC_N(double, n);
522
- for (int i = 0; i < n; i++)
523
- if (argn > 0) {
524
- u[i] = NUM2DBL(RARRAY_PTR(vargu)[i]);
525
- if (u[i] < x || y < u[i] || (i > 0 && u[i] <= u[i-1]))
526
- rb_raise(rb_eArgError, "Illegal argument");
527
- } else {
528
- u[i] = x + i * (y - x) / (n - 1);
529
- rb_ary_push(vargu, rb_float_new(u[i]));
530
- }
531
- x = (argc >= 3) ? NUM2DBL(vargx) : u[0];
532
- y = (argc == 4) ? NUM2DBL(vargy) : 0 ;
533
- bspline<double> *result;
534
- try {
535
- result = arg0->line_integral(ufunc, n, u, x, y);
536
- } catch (const char *c) {
537
- rb_raise(rb_eRuntimeError, "%s", c);
538
- }
539
- free(u);
540
- return Wrap_bspline(cBspline, result);
541
- }
542
-
543
- static VALUE _wrap_bspline_mul(VALUE self, VALUE varg);
544
-
545
- static void
546
- _wrap_Init_bspline(void)
547
- {
548
- cBspline = rb_define_class_under(mPspline, "Bspline", rb_cObject);
549
- rb_include_module(cBspline, rb_mEnumerable);
550
- rb_define_singleton_method(cBspline, "new", VALUEFUNC(_wrap_new_bspline), -1);
551
- rb_define_method(cBspline, "initialize", VALUEFUNC(_wrap_init_bspline), -1);
552
- rb_define_method(cBspline, "[]", VALUEFUNC(_wrap_bspline_bracket), -1);
553
- rb_define_method(cBspline, "value", VALUEFUNC(_wrap_bspline_value), -1);
554
- rb_define_method(cBspline, "sekibun", VALUEFUNC(_wrap_bspline_sekibun), 1);
555
- rb_define_method(cBspline, "plot", VALUEFUNC(_wrap_bspline_plot), -1);
556
- rb_define_method(cBspline, "line_integral", VALUEFUNC(_wrap_bspline_lint), -1);
557
- rb_define_method(cBspline, "*", VALUEFUNC(_wrap_bspline_mul), 1);
558
- rb_define_module_function(mPspline, "fft_complex_transform", VALUEFUNC(_wrap_complex_trans), 2);
559
- rb_define_module_function(mPspline, "fft_complex_get", VALUEFUNC(_wrap_complex_get), 2);
560
- rb_define_module_function(mPspline, "fft_complex_bspline", VALUEFUNC(_wrap_complex_bspline), 2);
561
- rb_define_module_function(mPspline, "fft_real_transform", VALUEFUNC(_wrap_real_trans), 2);
562
- rb_define_module_function(mPspline, "fft_real_get", VALUEFUNC(_wrap_real_get), 2);
563
- rb_define_module_function(mPspline, "fft_real_bspline", VALUEFUNC(_wrap_real_bspline), 2);
564
- }
565
-
566
- static VALUE cPspline;
567
-
568
- static void Wrap_free_pspline(pspline<double> *arg0) { delete arg0; }
569
-
570
- #define Wrap_pspline(klass, ptr) (\
571
- (ptr) ? Data_Wrap_Struct(klass, 0, VOIDFUNC(Wrap_free_pspline), ptr) : Qnil )
572
-
573
- #define Get_pspline(val, ptr) {\
574
- if (NIL_P(val)) ptr = NULL;\
575
- else {\
576
- if (!rb_obj_is_kind_of(val, cPspline))\
577
- rb_raise(rb_eTypeError, "wrong argument type (expected pspline)");\
578
- Data_Get_Struct(val, pspline<double>, ptr);\
579
- if (!ptr) rb_raise(rb_eRuntimeError, "This pspline already released");\
580
- }\
581
- }
582
-
583
- // Pspline#new()
584
-
585
- static VALUE
586
- _wrap_new_pspline(int argc, VALUE *argv, VALUE klass)
587
- {
588
- VALUE self = Data_Wrap_Struct(klass, 0, VOIDFUNC(Wrap_free_pspline), 0);
589
- rb_obj_call_init(self, argc, argv);
590
- return self;
591
- }
592
-
593
- #define Get_param(N, varg, ptr, str) {\
594
- Check_Type(varg, T_ARRAY);\
595
- int k = RARRAY_LEN(varg);\
596
- if (k != N)\
597
- rb_raise(rb_eArgError, "%s list length = %d, it should be %d", str, k, N);\
598
- ptr = ALLOC_N(int, k);\
599
- for (int i = 0; i < k; ++i) ptr[i] = NUM2INT(RARRAY_PTR(varg)[i]);\
600
- }
601
-
602
- static comb_array<double> make_var(int N, VALUE var, int *n = NULL, int *m = NULL)
603
- {
604
- int M = 0, s[N]; VALUE vs[N];
605
- for (int i = 0; i < N; ++i) {
606
- vs[i] = RARRAY_PTR(var)[i];
607
- Check_Type(vs[i], T_ARRAY);
608
- s[i] = RARRAY_LEN(vs[i]);
609
- if (n != NULL && m != NULL) {
610
- int vars = n[i] + m[i]%2;
611
- if (s[i] != vars)
612
- rb_raise(rb_eArgError, "Elements = %d, it should be %d", s[i], vars);
613
- }
614
- M += s[i];
615
- }
616
- double v[M], *p = v;
617
- for (int i = 0; i < N; ++i)
618
- for (int j = 0; j < s[i]; ++j)
619
- *p++ = NUM2DBL(RARRAY_PTR(vs[i])[j]);
620
- return comb_array<double>(v, N, s, 1);
621
- }
622
-
623
- static VALUE make_flat(int K, VALUE val, int N, int *n)
624
- {
625
- if (N == 0) return val;
626
- if (K != n[0]) rb_raise(rb_eArgError, "Wrong argument Array");
627
- VALUE vals = rb_ary_new();
628
- for (int i = 0; i < K; ++i) {
629
- VALUE va = RARRAY_PTR(val)[i];
630
- if (TYPE(va) == T_ARRAY) {
631
- VALUE vb = rb_obj_dup(va);
632
- vals = rb_ary_concat(vals, make_flat(RARRAY_LEN(va), vb, N-1, n+1));
633
- }
634
- else
635
- rb_ary_push(vals, va);
636
- }
637
- return vals;
638
- }
639
-
640
- static poly_array<double> make_val(int &K, VALUE val, int N, int *n)
641
- {
642
- if (K != n[0]) rb_raise(rb_eArgError, "Member size = %d, it should be %d", K, n[0]);
643
- VALUE vals = rb_ary_new();
644
- for (int i = 0; i < K; ++i) {
645
- VALUE va = RARRAY_PTR(val)[i];
646
- if (TYPE(va) == T_ARRAY) {
647
- VALUE vb = rb_obj_dup(va);
648
- vals = rb_ary_concat(vals, make_flat(RARRAY_LEN(va), vb, N-1, n+1));
649
- }
650
- else
651
- rb_ary_push(vals, va);
652
- }
653
- int M = RARRAY_LEN(vals);
654
- K = M;
655
- for (int i = 0; i < N; ++i) K /= n[i];
656
- double v[M];
657
- for (int i = 0; i < M; ++i) v[i] = NUM2DBL(RARRAY_PTR(vals)[i]);
658
- return poly_array<double>(v, N, n, K);
659
- }
660
- /*******************************************************************************
661
- Calculate interpolation of N variable M dimension P-spline.
662
- Pspline.new([X^Y^...], [S,T,...], N, J, S)
663
- X^Y^...:点の座標
664
- S,T,...:変数の座標
665
- N:
666
- J:スプライン次数(階数K=J+1)
667
- S:
668
- Result:P-spline object
669
- *******************************************************************************/
670
-
671
- // Pspline#initialize
672
-
673
- static VALUE
674
- _wrap_init_pspline(int argc, VALUE *argv, VALUE self)
675
- {
676
- VALUE vxyz, vstu, vargn, vargj, vargs;
677
-
678
- int N, K, *n, *j, *s;
679
-
680
- rb_scan_args(argc, argv, "5", &vxyz, &vstu, &vargn, &vargj, &vargs);
681
-
682
- Check_Type(vstu, T_ARRAY);
683
- N = RARRAY_LEN(vstu);
684
-
685
- Get_param(N, vargs, s, "Type");
686
-
687
- Get_param(N, vargj, j, "Degree");
688
-
689
- Get_param(N, vargn, n, "Size");
690
-
691
- Check_Type(vxyz, T_ARRAY);
692
- K = RARRAY_LEN(vxyz);
693
-
694
- try {
695
-
696
- comb_array<double> stu = make_var(N, vstu, n, s);
697
- poly_array<double> xyz = make_val(K, vxyz, N, n);
698
-
699
- Int argn(N, n, K);
700
- Int argj(N, j, 0);
701
- Int args(N, s, 0);
702
- // argn.print(", "); argj.print(", "); args.print("\n");
703
- // stu.print("\n"); xyz.print("\n");
704
- DATA_PTR(self) = new pspline<double>(xyz, stu, argj, args);
705
-
706
- } catch (const char *c) {
707
- rb_raise(rb_eRuntimeError, "%s", c);
708
- }
709
- free(n);
710
- free(j);
711
- free(s);
712
- return self;
713
- }
714
- /*******************************************************************************
715
- 関数値
716
-
717
- pspline#[x[, ...]]
718
- x:点のX座標(数値,または数値の配列)
719
-
720
- Result:補間値
721
- *******************************************************************************/
722
- static VALUE
723
- _wrap_pspline_bracket(int argc, VALUE *argv, VALUE self)
724
- {
725
- pspline<double> *bsp;
726
- VALUE vargs, vresult, mresult = Qnil;
727
-
728
- Get_pspline(self, bsp);
729
- int N = bsp->Grid();
730
- int K = bsp->Unit_size();
731
- mresult = rb_ary_new();
732
- try {
733
- for (int m = 0; m < argc; ++m) {
734
- vargs = argv[m];
735
- poly_array<double> val;
736
- if (TYPE(vargs) == T_ARRAY) {
737
- int L = RARRAY_LEN(vargs);
738
- if (L != N)
739
- rb_raise(rb_eArgError, "Array length = %d, it should be %d.", L, N);
740
- double args[N+1];
741
- for (int i = 0; i < N; ++i)
742
- args[i] = NUM2DBL(RARRAY_PTR(vargs)[i]);
743
- poly<double> arg(args, N);
744
- val = (*bsp)[arg];
745
- } else
746
- val = (*bsp)[NUM2DBL(vargs)];
747
- if (K == 1)
748
- vresult = rb_float_new(val[0]);
749
- else {
750
- vresult = rb_ary_new();
751
- for (int j = 0; j < K; ++j)
752
- rb_ary_push(vresult, rb_float_new(val[j]));
753
- }
754
- rb_ary_push(mresult, vresult);
755
- }
756
- } catch (const char *c) {
757
- rb_raise(rb_eRuntimeError, "%s", c);
758
- }
759
- return argc == 1 ? rb_ary_shift(mresult) : mresult;
760
- }
761
-
762
- void ps_eArgError(VALUE err)
763
- {
764
- VALUE str = rb_String(err);
765
- rb_raise(rb_eArgError, "wrong argument %s", StringValuePtr(str));
766
- }
767
- /*******************************************************************************
768
- 関数値
769
- pspline#value(x, d = 0)
770
- x:点のX座標
771
- d:微分階数(省略可)
772
- Result:補間値,または微分値
773
- *******************************************************************************/
774
- static VALUE
775
- _wrap_pspline_value(int argc, VALUE *argv, VALUE self)
776
- {
777
- VALUE varg1, varg2, varg3;
778
- pspline<double> *arg0;
779
- int argn, arg2 = 0, *carg2 = NULL;
780
- double arg1, *args, *carg3 = NULL;
781
- VALUE vargs, vresult = Qnil;
782
-
783
- rb_scan_args(argc, argv, "12", &varg1, &varg2, &varg3);
784
-
785
- Get_pspline(self, arg0);
786
- int N = arg0->Grid();
787
- int K = arg0->Unit_size();
788
- // 全微分
789
- if (argc == 3) {
790
- arg2 = NUM2INT(varg2);
791
- carg3 = new double[N];
792
- Check_Type(varg3, T_ARRAY);
793
- if (RARRAY_LEN(varg3) != N) ps_eArgError(varg3);
794
- for (int i = 0; i < N; ++i)
795
- carg3[i] = NUM2DBL(RARRAY_PTR(varg3)[i]);
796
- }
797
- // 偏微分
798
- if (argc == 2) {
799
- if (TYPE(varg2) == T_ARRAY && RARRAY_LEN(varg2) == N) {
800
- carg2 = new int[N];
801
- for (int i = 0; i < N; ++i)
802
- carg2[i] = NUM2INT(RARRAY_PTR(varg2)[i]);
803
- } else if (TYPE(varg1) != T_ARRAY) {
804
- arg2 = NUM2INT(varg2);
805
- argc = 0;
806
- } else ps_eArgError(varg2);
807
- }
808
- // Argument list
809
- poly<double> arg;
810
- args = NULL;
811
- if (TYPE(varg1) == T_ARRAY) {
812
- argn = RARRAY_LEN(varg1);
813
- vargs = make_list(argn, RARRAY_PTR(varg1));
814
- argn = RARRAY_LEN(vargs);
815
- if (argn == N) {
816
- args = new double[N+1];
817
- for (int i = 0; i < N; ++i)
818
- args[i] = NUM2DBL(RARRAY_PTR(vargs)[i]);
819
- } else ps_eArgError(varg1);
820
- } else
821
- if (argc <= 1) arg1 = NUM2DBL(varg1);
822
- else ps_eArgError(varg1);
823
- if (argc < 2) argc ^= 1;
824
- if (args) arg = poly<double>(args, N);
825
- poly_array<double> val;
826
- try {
827
- switch (argc) {
828
- case 0: // 関数値
829
- val = args ? (*arg0)(arg) : (*arg0)(arg1);
830
- delete[] args;
831
- break;
832
- case 1: // 関数積の微分
833
- val = (*arg0)(arg1, arg2);
834
- delete[] args;
835
- break;
836
- case 2: // 偏微分 (partial derivative)
837
- val = (*arg0)(arg, carg2);
838
- delete[] carg2;
839
- break;
840
- case 3: // 全微分 (total derivative)
841
- val = (*arg0)(arg, arg2, carg3);
842
- delete[] carg3;
843
- }
844
- } catch (const char *c) {
845
- rb_raise(rb_eRuntimeError, "%s", c);
846
- }
847
- if (K == 1)
848
- vresult = rb_float_new(val[0]);
849
- else {
850
- vresult = rb_ary_new();
851
- for (int j = 0; j < K; ++j)
852
- rb_ary_push(vresult, rb_float_new(val[j]));
853
- }
854
- return vresult;
855
- }
856
-
857
- static VALUE
858
- _wrap_pspline_sekibun(int argc, VALUE *argv, VALUE self)
859
- {
860
- pspline<double> *bsp;
861
- VALUE vargs, vresult = Qnil;
862
-
863
- Get_pspline(self, bsp);
864
- int N = bsp->Grid();
865
- int K = bsp->Unit_size();
866
-
867
- vargs = make_list(argc, argv);
868
- argc = RARRAY_LEN(vargs);
869
- try {
870
- if (argc == N || argc == 1) {
871
- double s[N+1];
872
- for (int i = 0; i < N; ++i)
873
- if (i == 0 || argc == N)
874
- s[i] = NUM2DBL(RARRAY_PTR(vargs)[i]);
875
- else
876
- s[i] = s[i-1];
877
- poly<double> args(s, N);
878
- poly_array<double> val = bsp->sekibun(args);
879
- if (K == 1)
880
- vresult = rb_float_new(val[0]);
881
- else {
882
- vresult = rb_ary_new();
883
- for (int j = 0; j < K; ++j)
884
- rb_ary_push(vresult, rb_float_new(val[j]));
885
- }
886
- } else rb_raise(rb_eArgError, "wrong argument Sekibun");
887
- } catch (const char *c) {
888
- rb_raise(rb_eRuntimeError, "%s", c);
889
- }
890
- return vresult;
891
- }
892
-
893
- static VALUE
894
- _wrap_pspline_plot(int argc, VALUE *argv, VALUE self)
895
- {
896
- pspline<double> *arg0;
897
- VALUE vstu, varg, vdp, vjbn;
898
- int arg3, *arg4 = NULL;
899
-
900
- rb_scan_args(argc, argv, "21", &varg, &vdp, &vjbn);
901
-
902
- Get_pspline(self, arg0);
903
- int N = arg0->Grid();
904
- int K = arg0->Unit_size();
905
- double *arg1[N], *arg2[K];
906
- arg3 = NUM2INT(vdp);
907
- if (argc > 2) {
908
- arg4 = new int[N];
909
- if (TYPE(vjbn) == T_ARRAY) {
910
- int n = RARRAY_LEN(vjbn);
911
- if (n != N)
912
- rb_raise(rb_eArgError, "Differential orders = %d, it should be %d", n, N);
913
- for (int i = 0; i < N; ++i)
914
- arg4[i] = NUM2INT(RARRAY_PTR(vjbn)[i]);
915
- } else
916
- arg4[0] = NUM2INT(vjbn);
917
- }
918
- Check_Type(varg, T_ARRAY);
919
- N = RARRAY_LEN(varg);
920
- vstu = rb_ary_new();
921
- int result;
922
- for (int i = 0; i < N; ++i) rb_ary_push(vstu, rb_ary_shift(varg));
923
- try {
924
- if (TYPE(RARRAY_PTR(vstu)[0]) == T_ARRAY) {
925
- comb_array<double> stu = make_var(N, vstu);
926
- result = plot<double>(*arg0, stu, arg1, arg2, arg3, arg4);
927
- } else {
928
- double *x = new double[N];
929
- for (int i = 0; i < N; i++) x[i] = NUM2DBL(RARRAY_PTR(vstu)[i]);
930
- result = plot<double>(*arg0, N, x, arg1, arg2, arg3, arg4[0]);
931
- delete[] x;
932
- N = 1;
933
- }
934
- } catch (const char *c) {
935
- rb_raise(rb_eRuntimeError, "%s", c);
936
- }
937
- delete[] arg4;
938
- for (int i = 0; i < result; i++) {
939
- VALUE v1 = rb_ary_new();
940
- for (int j = 0; j < N; ++j) rb_ary_push(v1, rb_float_new(arg1[j][i]));
941
- VALUE v2 = rb_ary_new();
942
- for (int k = 0; k < K; ++k) rb_ary_push(v2, rb_float_new(arg2[k][i]));
943
- VALUE vv = rb_ary_new();
944
- rb_ary_push(vv, v1);
945
- rb_ary_push(vv, v2);
946
- rb_ary_push(varg, vv);
947
- if (rb_block_given_p()) rb_yield(vv);
948
- }
949
- for (int i = 0; i < N; ++i) FREE(arg1[i]);
950
- for (int i = 0; i < K; ++i) FREE(arg2[i]);
951
- return INT2NUM(result);
952
- }
953
-
954
- static VALUE
955
- _wrap_bspline_mul(VALUE self, VALUE varg)
956
- {
957
- bspline<double> *arg0;
958
- Get_bspline(self, arg0);
959
- pspline<double> *result;
960
- if (rb_obj_is_kind_of(varg, cBspline)) {
961
- bspline<double> *arg1;
962
- Data_Get_Struct(varg, bspline<double>, arg1);
963
- if (!arg1) rb_raise(rb_eArgError, "Not Bspline object");
964
- result = new pspline<double>((*arg0) * (*arg1));
965
- } else if (rb_obj_is_kind_of(varg, cPspline)) {
966
- pspline<double> *arg1;
967
- Data_Get_Struct(varg, pspline<double>, arg1);
968
- if (!arg1) rb_raise(rb_eArgError, "Not Pspline Object");
969
- result = new pspline<double>((*arg0) * (*arg1));
970
- } else {
971
- double a = NUM2DBL(varg);
972
- bspline<double> *result = new bspline<double>(*arg0);
973
- double *p = *result;
974
- int k = result->Unit_size();
975
- int c = ((base_spline<double>*)result)->Icox();
976
- for (int i = 0; i < c * k; i++) p[i] *= a;
977
- return Wrap_bspline(cBspline, result);
978
- }
979
- return Wrap_pspline(cPspline, result);
980
- }
981
-
982
- static VALUE
983
- _wrap_pspline_mul(VALUE self, VALUE varg)
984
- {
985
- pspline<double> *arg0;
986
- Get_pspline(self, arg0);
987
- pspline<double> *result;
988
- if (rb_obj_is_kind_of(varg, cBspline)) {
989
- bspline<double> *arg1;
990
- Data_Get_Struct(varg, bspline<double>, arg1);
991
- if (!arg1) rb_raise(rb_eArgError, "Not Bspline object");
992
- result = new pspline<double>((*arg0) * (*arg1));
993
- }/* else if (rb_obj_is_kind_of(varg, cPspline)) {
994
- pspline<double> *arg1;
995
- Data_Get_Struct(varg, pspline<double>, arg1);
996
- if (!arg1) rb_raise(rb_eArgError, "Not Pspline object");
997
- result = new pspline<double>((*arg0) * (*arg1));
998
- }*/ else {
999
- double a = NUM2DBL(varg);
1000
- result = new pspline<double>(*arg0);
1001
- double *p = *result;
1002
- const Int& c = result->values->icox;
1003
- int s = c.grid_size();
1004
- for (int i = 0; i < s; i++) p[i] *= a;
1005
- }
1006
- return Wrap_pspline(cPspline, result);
1007
- }
1008
-
1009
- static void
1010
- _wrap_Init_pspline(void)
1011
- {
1012
- cPspline = rb_define_class_under(mPspline, "Pspline", rb_cObject);
1013
- rb_include_module(cPspline, rb_mEnumerable);
1014
- rb_define_singleton_method(cPspline, "new", VALUEFUNC(_wrap_new_pspline), -1);
1015
- rb_define_method(cPspline, "initialize", VALUEFUNC(_wrap_init_pspline), -1);
1016
- rb_define_method(cPspline, "[]", VALUEFUNC(_wrap_pspline_bracket), -1);
1017
- rb_define_method(cPspline, "value", VALUEFUNC(_wrap_pspline_value), -1);
1018
- rb_define_method(cPspline, "sekibun", VALUEFUNC(_wrap_pspline_sekibun), -1);
1019
- rb_define_method(cPspline, "plot", VALUEFUNC(_wrap_pspline_plot), -1);
1020
- rb_define_method(cPspline, "*", VALUEFUNC(_wrap_pspline_mul), 1);
1021
- }
1022
-
1023
- #ifdef __cplusplus
1024
- extern "C" {
1025
- #endif
1026
-
1027
- void Init_pspline(void)
1028
- {
1029
- mPspline = rb_define_module("PSPLINE");
1030
-
1031
- _wrap_Init_bspline();
1032
- _wrap_Init_pspline();
1033
- }
1034
-
1035
- #ifdef __cplusplus
1036
- }
1037
- #endif
1038
-
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
+ #define PSPLINE
29
+ #define DTYPE dd
30
+
31
+ #include "bspline.h"
32
+ #include "basis/fft.h"
33
+
34
+ static VALUE mPspline;
35
+
36
+ static VALUE cBspline;
37
+
38
+ static void Wrap_free_bspline(bspline<double> *arg0) { delete arg0; }
39
+
40
+ #define Wrap_bspline(klass, ptr) (\
41
+ (ptr) ? Data_Wrap_Struct(klass, 0, VOIDFUNC(Wrap_free_bspline), ptr) : Qnil )
42
+
43
+ #define Get_bspline(val, ptr) {\
44
+ if (NIL_P(val)) ptr = NULL;\
45
+ else {\
46
+ if (!rb_obj_is_kind_of(val, cBspline))\
47
+ rb_raise(rb_eTypeError, "wrong argument type (expected bspline)");\
48
+ Data_Get_Struct(val, bspline<double>, ptr);\
49
+ if (!ptr) rb_raise(rb_eRuntimeError, "This bspline already released");\
50
+ }\
51
+ }
52
+
53
+ // bspline#new()
54
+
55
+ static VALUE
56
+ _wrap_new_bspline(int argc, VALUE *argv, VALUE klass)
57
+ {
58
+ VALUE self = Data_Wrap_Struct(klass, 0, VOIDFUNC(Wrap_free_bspline), 0);
59
+ rb_obj_call_init(self, argc, argv);
60
+ return self;
61
+ }
62
+ /*******************************************************************************
63
+ Calculate interpolation of 1 variable M dimension B-spline.
64
+ bspline.new([...,[Xi,Yi0,...,YiM-1],...], N, J, S)
65
+ X0,..,Xi,..,XN-1:点のX座標
66
+ Yi0, ..., YiM-1:点のY座標
67
+ J:スプライン次数(階数K=J+1)
68
+ Result:B-spline object
69
+ *******************************************************************************/
70
+
71
+ // bspline#initialize
72
+
73
+ static VALUE
74
+ _wrap_init_bspline(int argc, VALUE *argv, VALUE self)
75
+ {
76
+ VALUE va, varg, vargn, vargj, vargs, vargd = Qnil;
77
+ int argp, argn, argj, args = 0, k = 1;
78
+ int *argd = NULL;
79
+
80
+ rb_scan_args(argc, argv, "31", &varg, &vargn, &vargj, &vargs);
81
+
82
+ Check_Type(varg, T_ARRAY);
83
+ argp = RARRAY_LEN(varg);
84
+ argn = NUM2INT(vargn);
85
+ argj = NUM2INT(vargj);
86
+ int D = argp - argn;
87
+ if (D < 0)
88
+ rb_raise(rb_eArgError, "Data points %d < Data size %d", argp, argn);
89
+ if (D > argj)
90
+ rb_raise(rb_eArgError, "Additional points %d > Degree %d", D, argj);
91
+ if (argn <= argj)
92
+ rb_raise(rb_eArgError, "Data points %d <= Degree %d", argn, argj);
93
+ if (argc > 3) {
94
+ vargd = argv[3];
95
+ if (TYPE(vargd) == T_ARRAY) {
96
+ int d = RARRAY_LEN(vargd);
97
+ if (d != D)
98
+ rb_raise(rb_eArgError, "Differential orders = %d, it should be %d", d, D);
99
+ argd = ALLOC_N(int, argn + D);
100
+ for (int i = 0; i < argn; ++i)
101
+ argd[i] = 0;
102
+ for (int i = 0; i < D; ++i)
103
+ argd[argn + i] = NUM2INT(RARRAY_PTR(vargd)[i]);
104
+ } else
105
+ args = NUM2INT(vargs);
106
+ }
107
+ va = RARRAY_PTR(varg)[0];
108
+ Check_Type(va, T_ARRAY);
109
+ k = RARRAY_LEN(va) - 1;
110
+ Vector x(size_t(argp), DTYPE);
111
+ Vector y(size_t(argp * k), DTYPE);
112
+ for (int i = 0; i < argp; i++) {
113
+ if (i > 0) {
114
+ va = RARRAY_PTR(varg)[i];
115
+ Check_Type(va, T_ARRAY);
116
+ if (RARRAY_LEN(va) - 1 != k)
117
+ rb_raise(rb_eArgError, "Dimension should be %d", k);
118
+ }
119
+ for (int j = 0; j <= k; ++j) {
120
+ VALUE X = RARRAY_PTR(va)[j];
121
+ if (TYPE(X) == T_STRING)
122
+ if (j == 0) x[i] = StringValuePtr(X);
123
+ else y[i*k+j-1] = StringValuePtr(X);
124
+ else
125
+ if (j == 0) x[i] = NUM2DBL(X);
126
+ else y[i*k+j-1] = NUM2DBL(X);
127
+ }
128
+ }
129
+ try {
130
+ Real_array argy((double*)y, argp - (args%2), k, DTYPE);
131
+ // printf("n = %d, j = %d, s = %d\n", argn, argj, args);
132
+ // x.print("%g\n"); argy.print("%g\n");
133
+ DATA_PTR(self) = new bspline<double>(argy, x, argn + (args%2), argj, args, argd);
134
+ // ((bspline<double>*)DATA_PTR(self))->print("%f\n");
135
+ } catch (const char *c) {
136
+ rb_raise(rb_eRuntimeError, "%s", c);
137
+ }
138
+ if (argd) free(argd);
139
+ return self;
140
+ }
141
+
142
+ static VALUE
143
+ make_list(int argc, VALUE *argv)
144
+ {
145
+ VALUE vargs = rb_ary_new();
146
+ for (int i = 0; i < argc; i++) {
147
+ if (TYPE(argv[i]) == T_ARRAY) {
148
+ VALUE val = rb_obj_dup(argv[i]);
149
+ vargs = rb_ary_concat(vargs, _wrap_ary_flatten(val));
150
+ }
151
+ else
152
+ rb_ary_push(vargs, argv[i]);
153
+ }
154
+ return vargs;
155
+ }
156
+ /*******************************************************************************
157
+ 関数値
158
+
159
+ bspline#[x[, ...]]
160
+ x:点のX座標(数値,または数値の配列)
161
+
162
+ Result:補間値
163
+ *******************************************************************************/
164
+ static VALUE
165
+ _wrap_bspline_bracket(int argc, VALUE *argv, VALUE self)
166
+ {
167
+ bspline<double> *bsp;
168
+ Real arg; char *fmt = NULL, *num;
169
+ VALUE val, vargs;
170
+ VALUE vresult = Qnil;
171
+
172
+ Get_bspline(self, bsp);
173
+ int K = bsp->Unit();
174
+
175
+ vargs = make_list(argc, argv);
176
+ argc = RARRAY_LEN(vargs);
177
+ try {
178
+ vresult = rb_ary_new();
179
+ for (int i = 0; i < argc; i++) {
180
+ VALUE varg = RARRAY_PTR(vargs)[i];
181
+ if (TYPE(varg) == T_STRING) {
182
+ num = StringValuePtr(varg);
183
+ char *c = num;
184
+ if (*c == '%') { ++c;
185
+ while((*c >= '0' && *c <= '9') || *c == '.') ++c;
186
+ if (*c >= 'e' && *c <= 'g') {
187
+ fmt = num; continue;
188
+ }
189
+ }
190
+ arg = num;
191
+ } else
192
+ arg = NUM2DBL(varg);
193
+ Vector result = (*bsp)[arg];
194
+ // arg.print("f(%g)"); result.print(" = %g\n");
195
+ if (K == 1){
196
+ if (fmt) {
197
+ num = result[0].to_s(fmt);
198
+ val = rb_str_new2(num);
199
+ delete[] num;
200
+ } else
201
+ val = rb_float_new(result[0](0));
202
+ } else {
203
+ val = rb_ary_new();
204
+ for (int j = 0; j < K; ++j) {
205
+ if (fmt) {
206
+ num = result[j].to_s(num);
207
+ rb_ary_push(val, rb_str_new2(num));
208
+ delete[] num;
209
+ } else
210
+ rb_ary_push(val, rb_float_new(result[j](0)));
211
+ }
212
+ }
213
+ rb_ary_push(vresult, val);
214
+ }
215
+ } catch (const char *c) {
216
+ rb_raise(rb_eRuntimeError, "%s", c);
217
+ }
218
+ return argc == 1 ? rb_ary_shift(vresult) : vresult;
219
+ }
220
+ /*******************************************************************************
221
+ 関数値
222
+ bspline#value(x, d = 0)
223
+ x:点のX座標
224
+ d:微分階数(省略可)
225
+ Result:補間値,または微分値
226
+ *******************************************************************************/
227
+ static VALUE
228
+ _wrap_bspline_value(int argc, VALUE *argv, VALUE self)
229
+ {
230
+ VALUE varg0, varg1, varg2 ;
231
+ bspline<double> *arg0 ;
232
+ Real arg1((size_t)DTYPE);
233
+ int arg2 = 0 ; char *fmt = NULL, *num;
234
+ VALUE vresult = Qnil;
235
+
236
+ rb_scan_args(argc, argv, "21", &varg0, &varg1, &varg2);
237
+ if (TYPE(varg0) == T_STRING) {
238
+ num = StringValuePtr(varg0);
239
+ char *c = num;
240
+ if (*c == '%') { ++c;
241
+ while((*c >= '0' && *c <= '9') || *c == '.') ++c;
242
+ if (*c >= 'e' && *c <= 'g') {
243
+ fmt = num;
244
+ }
245
+ }
246
+ if (fmt) {
247
+ if (TYPE(varg1) == T_STRING)
248
+ arg1 = StringValuePtr(varg1);
249
+ else
250
+ arg1 = NUM2DBL(varg1);
251
+ if (argc > 2) arg2 = NUM2DBL(varg2);
252
+ } else {
253
+ arg1 = num;
254
+ arg2 = NUM2INT(varg1);
255
+ }
256
+ } else {
257
+ arg1 = NUM2DBL(varg0);
258
+ arg2 = NUM2INT(varg1);
259
+ }
260
+ Get_bspline(self, arg0);
261
+ int K = arg0->Unit();
262
+ try {
263
+ Vector result = (*arg0)(arg1, arg2);
264
+ if (K == 1) {
265
+ if (fmt) {
266
+ num = result[0].to_s(fmt);
267
+ vresult = rb_str_new2(num);
268
+ delete[] num;
269
+ } else
270
+ vresult = rb_float_new(result[0](0));
271
+ }
272
+ else {
273
+ vresult = rb_ary_new();
274
+ for (int j = 0; j < K; ++j) {
275
+ if (fmt) {
276
+ num = result[j].to_s(fmt);
277
+ rb_ary_push(vresult, rb_str_new2(num));
278
+ delete[] num;
279
+ } else
280
+ rb_ary_push(vresult, rb_float_new(result[j](0)));
281
+ }
282
+ }
283
+ } catch (const char *c) {
284
+ rb_raise(rb_eRuntimeError, "%s", c);
285
+ }
286
+ return vresult;
287
+ }
288
+
289
+ static VALUE
290
+ _wrap_bspline_sekibun(int argc, VALUE *argv, VALUE self)
291
+ {
292
+ bspline<double> *arg0 ;
293
+ char *fmt = NULL, *num;
294
+ VALUE varg0, varg1; Real arg;
295
+ VALUE vresult = Qnil;
296
+
297
+ rb_scan_args(argc, argv, "11", &varg0, &varg1);
298
+ if (TYPE(varg0) == T_STRING) {
299
+ num = StringValuePtr(varg0);
300
+ char *c = num;
301
+ if (*c == '%') { ++c;
302
+ while((*c >= '0' && *c <= '9') || *c == '.') ++c;
303
+ if (*c >= 'e' && *c <= 'g') {
304
+ fmt = num;
305
+ }
306
+ }
307
+ if (fmt) {
308
+ if (TYPE(varg1) == T_STRING)
309
+ arg = StringValuePtr(varg1);
310
+ else
311
+ arg = NUM2DBL(varg1);
312
+ } else
313
+ arg = num;
314
+ } else
315
+ arg = NUM2DBL(varg0);
316
+ Get_bspline(self, arg0);
317
+ int K = arg0->Unit();
318
+ try {
319
+ Vector result = arg0->sekibun(arg);
320
+ if (K == 1) {
321
+ if (fmt) {
322
+ num = result[0].to_s(fmt);
323
+ vresult = rb_str_new2(num);
324
+ delete[] num;
325
+ } else
326
+ vresult = rb_float_new(result[0](0));
327
+ }
328
+ else {
329
+ vresult = rb_ary_new();
330
+ for (int j = 0; j < K; ++j) {
331
+ if (fmt) {
332
+ num = result[j].to_s(fmt);
333
+ rb_ary_push(vresult, rb_str_new2(num));
334
+ delete[] num;
335
+ } else
336
+ rb_ary_push(vresult, rb_float_new(result[j](0)));
337
+ }
338
+ }
339
+ } catch (const char *c) {
340
+ rb_raise(rb_eRuntimeError, "%s", c);
341
+ }
342
+ return vresult;
343
+ }
344
+
345
+ static VALUE
346
+ _wrap_bspline_plot(int argc, VALUE *argv, VALUE self)
347
+ {
348
+ bspline<double> *arg0; // bspline object
349
+ VALUE varg1; // list of point
350
+ VALUE varg3; int arg3; // number of division
351
+ VALUE varg4; int arg4 = 0; // order differential
352
+
353
+ rb_scan_args(argc, argv, "21", &varg1, &varg3, &varg4);
354
+
355
+ Check_Type(varg1, T_ARRAY);
356
+ arg3 = NUM2INT(varg3);
357
+ if (argc > 2) arg4 = NUM2INT(varg4);
358
+ Get_bspline(self, arg0);
359
+
360
+ int argn = RARRAY_LEN(varg1);
361
+ Vector argu(size_t(argn), DTYPE);
362
+ for (int i = 0; i < argn; ++i) {
363
+ VALUE x = rb_ary_shift(varg1);
364
+ if (TYPE(x) == T_STRING)
365
+ argu[i] = StringValuePtr(x);
366
+ else
367
+ argu[i] = NUM2DBL(x);
368
+ }
369
+ int K = arg0->Unit();
370
+ int result;
371
+ Matrix arg1, arg2;
372
+ try {
373
+ comb_array<double> argx((double*)argu, argn, DTYPE);
374
+ result = plot<double>(*arg0, argx, arg1, arg2, arg3, arg4);
375
+ } catch (const char *c) {
376
+ rb_raise(rb_eRuntimeError, "%s", c);
377
+ }
378
+ for (int i = 0; i < result; i++) {
379
+ // size_t n = i;
380
+ // Vector z1 = arg1[n]; printf("arg1[%d] = ", n); z1.print("%e, ");
381
+ // Vector z2 = arg2[n]; printf("arg2[%d] = ", n); z2.print("%e\n");
382
+ VALUE v1 = rb_float_new(arg1[i][0](0));
383
+ VALUE v2 = rb_ary_new();
384
+ for (int k = 0; k < K; ++k)
385
+ rb_ary_push(v2, rb_float_new(arg2[i][k](0)));
386
+ VALUE vv = rb_ary_new();
387
+ rb_ary_push(vv, v1);
388
+ rb_ary_push(vv, v2);
389
+ rb_ary_push(varg1, vv);
390
+ if (rb_block_given_p()) rb_yield(vv);
391
+ }
392
+ return INT2NUM(result);
393
+ }
394
+
395
+ static VALUE
396
+ _wrap_complex_trans(VALUE self, VALUE varg1, VALUE varg2)
397
+ {
398
+ VALUE varg, vargx, vargy, vresult = Qnil;
399
+ Check_Type(varg1, T_ARRAY);
400
+ int argn = RARRAY_LEN(varg1);
401
+ int argf = NUM2INT(varg2);
402
+ if (argf != 1) {
403
+ if (argn != 2) rb_raise(rb_eArgError, "Argument is not Complex");
404
+ vargx = RARRAY_PTR(varg1)[0]; Check_Type(vargx, T_ARRAY);
405
+ vargy = RARRAY_PTR(varg1)[1]; Check_Type(vargy, T_ARRAY);
406
+ argn = RARRAY_LEN(vargx);
407
+ if (argn != RARRAY_LEN(vargy)) rb_raise(rb_eArgError, "Argument is not Complex");
408
+ }
409
+ Vector data, dfft(size_t(argn << 1), DTYPE);
410
+ if (argf == 1) {
411
+ for (int i = 0; i < argn; i++) {
412
+ varg = RARRAY_PTR(varg1)[i];
413
+ Check_Type(varg, T_ARRAY);
414
+ if (RARRAY_LEN(varg) != 2) rb_raise(rb_eArgError, "Argument is not Complex");
415
+ dfft[2*i] = NUM2DBL(RARRAY_PTR(varg)[0]);
416
+ dfft[2*i+1] = NUM2DBL(RARRAY_PTR(varg)[1]);
417
+ }
418
+ try {
419
+ fft<>::complex_transform(dfft, argf);
420
+ data = fft<>::half_en_pack(dfft);
421
+ } catch (const char *c) {
422
+ rb_raise(rb_eRuntimeError, "%s", c);
423
+ }
424
+ vresult = rb_ary_new();
425
+ vargx = rb_ary_new();
426
+ vargy = rb_ary_new();
427
+ rb_ary_push(vresult, vargx);
428
+ rb_ary_push(vresult, vargy);
429
+ for (int i = 0; i < argn; i++) {
430
+ rb_ary_push(vargx, rb_float_new(data[i](0)));
431
+ rb_ary_push(vargy, rb_float_new(data[i+argn](0)));
432
+ }
433
+ } else {
434
+ for (int i = 0; i < argn; i++) {
435
+ dfft[i] = NUM2DBL(RARRAY_PTR(vargx)[i]);
436
+ dfft[i+argn] = NUM2DBL(RARRAY_PTR(vargy)[i]);
437
+ }
438
+ try {
439
+ data = fft<>::half_de_pack(dfft);
440
+ fft<>::complex_transform(data, argf);
441
+ } catch (const char *c) {
442
+ rb_raise(rb_eRuntimeError, "%s", c);
443
+ }
444
+ vresult = rb_ary_new();
445
+ for (int i = 0; i < argn; i++) {
446
+ varg = rb_ary_new();
447
+ rb_ary_push(vresult, varg);
448
+ rb_ary_push(varg, rb_float_new(data[2*i](0)));
449
+ rb_ary_push(varg, rb_float_new(data[2*i+1](0)));
450
+ }
451
+ }
452
+ return vresult;
453
+ }
454
+
455
+ static VALUE
456
+ _wrap_complex_get(VALUE self, VALUE varg1, VALUE varg2)
457
+ {
458
+ VALUE vargx, vargy, vresult = Qnil;
459
+ Check_Type(varg1, T_ARRAY);
460
+ int argn = RARRAY_LEN(varg1);
461
+ int args = NUM2INT(varg2);
462
+ if (argn != 2) rb_raise(rb_eArgError, "Argument is not Complex");
463
+ vargx = RARRAY_PTR(varg1)[0];
464
+ vargy = RARRAY_PTR(varg1)[1];
465
+ argn = RARRAY_LEN(vargx);
466
+ if (RARRAY_LEN(vargy) != argn) rb_raise(rb_eArgError, "Argument is not Complex");
467
+ Vector data(size_t(argn << 1), DTYPE);
468
+ for (int i = 0; i < argn; i++) {
469
+ data[i] = NUM2DBL(RARRAY_PTR(vargx)[i]);
470
+ data[i+argn] =NUM2DBL(RARRAY_PTR(vargy)[i]);
471
+ }
472
+ Vector w(size_t(2), DTYPE);
473
+ fft<>::half_get(data, args, w);
474
+ vresult = rb_ary_new();
475
+ rb_ary_push(vresult, rb_float_new(w[0](0)));
476
+ rb_ary_push(vresult, rb_float_new(w[1](0)));
477
+ return vresult;
478
+ }
479
+
480
+ static VALUE
481
+ _wrap_real_trans(VALUE self, VALUE varg1, VALUE varg2)
482
+ {
483
+ VALUE vresult = Qnil;
484
+ Check_Type(varg1, T_ARRAY);
485
+ int argn = RARRAY_LEN(varg1);
486
+ int argf = NUM2INT(varg2);
487
+ Vector data(size_t(argn), DTYPE);
488
+ for (int i = 0; i < argn; i++)
489
+ data[i] = NUM2DBL(RARRAY_PTR(varg1)[i]);
490
+ try {
491
+ fft<>::real_transform(data, argf);
492
+ } catch (const char *c) {
493
+ rb_raise(rb_eRuntimeError, "%s", c);
494
+ }
495
+ vresult = rb_ary_new();
496
+ for (int i = 0; i < argn; i++)
497
+ rb_ary_push(vresult, rb_float_new(data[i](0)));
498
+ return vresult;
499
+ }
500
+
501
+ static VALUE
502
+ _wrap_real_get(VALUE self, VALUE varg1, VALUE varg2)
503
+ {
504
+ VALUE vresult = Qnil;
505
+ Check_Type(varg1, T_ARRAY);
506
+ int argn = RARRAY_LEN(varg1);
507
+ int args = NUM2INT(varg2);
508
+ Vector data(size_t(argn), DTYPE);
509
+ for (int i = 0; i < argn; i++)
510
+ data[i] = NUM2DBL(RARRAY_PTR(varg1)[i]);
511
+ Vector w(size_t(2), DTYPE);
512
+ fft<>::real_get(data, args, w);
513
+ vresult = rb_ary_new();
514
+ rb_ary_push(vresult, rb_float_new(w[0](0)));
515
+ rb_ary_push(vresult, rb_float_new(w[1](0)));
516
+ return vresult;
517
+ }
518
+
519
+ static VALUE
520
+ _wrap_complex_bspline(VALUE self, VALUE varg1, VALUE varg2)
521
+ {
522
+ Check_Type(varg1, T_ARRAY);
523
+ int argn = RARRAY_LEN(varg1);
524
+ if (argn != 2) rb_raise(rb_eArgError, "Argument is not Complex");
525
+ VALUE vargx = RARRAY_PTR(varg1)[0];
526
+ VALUE vargy = RARRAY_PTR(varg1)[1];
527
+ Check_Type(vargx, T_ARRAY);
528
+ Check_Type(vargy, T_ARRAY);
529
+ argn = RARRAY_LEN(vargx);
530
+ if (RARRAY_LEN(vargy) != argn) rb_raise(rb_eArgError, "Argument is not Complex");
531
+ Vector data(size_t(argn << 1), DTYPE);
532
+ for (int i = 0; i < argn; i++) {
533
+ data[i] = NUM2DBL(RARRAY_PTR(vargx)[i]);
534
+ data[i+argn] = NUM2DBL(RARRAY_PTR(vargy)[i]);
535
+ }
536
+ Vector dfft = fft<>::half_de_pack(data);
537
+ int argj = NUM2INT(varg2);
538
+ bspline<> *result;
539
+ try {
540
+ result = fft<>::cfft_spline(dfft, argj);
541
+ } catch (const char *c) {
542
+ rb_raise(rb_eRuntimeError, "%s", c);
543
+ }
544
+ if (rb_block_given_p()) {
545
+ Vector val(size_t(2), DTYPE); int N = argn / 2;
546
+ for (int i = -N; i <= N + argn%2; i++) {
547
+ fft<>::half_get(data, i, val);
548
+ VALUE vv = rb_ary_new();
549
+ rb_ary_push(vv, INT2NUM(i));
550
+ VALUE xy = rb_ary_new();
551
+ rb_ary_push(xy, rb_float_new(val[0](0)));
552
+ rb_ary_push(xy, rb_float_new(val[1](0)));
553
+ rb_ary_push(vv, xy);
554
+ rb_yield(vv);
555
+ }
556
+ }
557
+ return Wrap_bspline(cBspline, result);
558
+ }
559
+
560
+ static VALUE
561
+ _wrap_real_bspline(VALUE self, VALUE varg1, VALUE varg2)
562
+ {
563
+ Check_Type(varg1, T_ARRAY);
564
+ int argn = RARRAY_LEN(varg1);
565
+ Vector data(size_t(argn), DTYPE);
566
+ for (int i = 0; i < argn; i++)
567
+ data[i] = NUM2DBL(RARRAY_PTR(varg1)[i]);
568
+ int argj = NUM2INT(varg2);
569
+ bspline<> *result;
570
+ try {
571
+ result = fft<>::rfft_spline(data, argj);
572
+ } catch (const char *c) {
573
+ rb_raise(rb_eRuntimeError, "%s", c);
574
+ }
575
+ if (rb_block_given_p()) {
576
+ Vector val(size_t(2), DTYPE); int N = argn / 2;
577
+ for (int i = -N; i <= N + argn%2; i++) {
578
+ fft<>::real_get(data, i, val);
579
+ VALUE vv = rb_ary_new();
580
+ rb_ary_push(vv, INT2NUM(i));
581
+ VALUE xy = rb_ary_new();
582
+ rb_ary_push(vv, xy);
583
+ rb_ary_push(xy, rb_float_new(val[0](0)));
584
+ rb_ary_push(xy, rb_float_new(val[1](0)));
585
+ rb_yield(vv);
586
+ }
587
+ }
588
+ return Wrap_bspline(cBspline, result);
589
+ }
590
+
591
+ static VALUE vfunc;
592
+
593
+ static Real ufunc(const Vector& pa)
594
+ {
595
+ int K = pa.size();
596
+ VALUE *vp = ALLOC_N(VALUE, K);
597
+ for (int i = 0; i < K; i++) vp[i] = rb_float_new(pa[i](0));
598
+ VALUE vresult = rb_funcall2(vfunc, rb_intern("call"), K, vp);
599
+ free(vp);
600
+ return Real(NUM2DBL(vresult), DTYPE);
601
+ }
602
+
603
+ static VALUE
604
+ _wrap_bspline_lint(int argc, VALUE *argv, VALUE self)
605
+ {
606
+ bspline<double> *arg0; // bspline object
607
+ VALUE vargu, vargx, vargy;
608
+ Get_bspline(self, arg0);
609
+ rb_scan_args(argc, argv, "22", &vfunc, &vargu, &vargx, &vargy);
610
+ int c = arg0->Icox(), j = arg0->Jisu(), n;
611
+ const Vector q = arg0->Knots();
612
+ const Real x = arg0->x_min();
613
+ const Real y = arg0->x_max();
614
+ Check_Type(vargu, T_ARRAY);
615
+ int argn = RARRAY_LEN(vargu);
616
+ n = argn > 0 ? argn : c - j + 1;
617
+ Vector u(size_t(n), DTYPE);
618
+ for (int i = 0; i < n; i++)
619
+ if (argn > 0) {
620
+ u[i] = NUM2DBL(RARRAY_PTR(vargu)[i]);
621
+ if (u[i] < x || y < u[i] || (i > 0 && u[i] <= u[i-1]))
622
+ rb_raise(rb_eArgError, "Illegal argument");
623
+ } else {
624
+ u[i] = x + i * (y - x) / (n - 1);
625
+ rb_ary_push(vargu, rb_float_new(u[i](0)));
626
+ }
627
+ Real a = (argc >= 3) ? NUM2DBL(vargx) : u[0];
628
+ Real b = (argc == 4) ? NUM2DBL(vargy) : 0 ;
629
+ comb_array<double> v((double*)u, n, DTYPE);
630
+ bspline<double> *result;
631
+ try {
632
+ result = arg0->line_integral(ufunc, v, a, b);
633
+ } catch (const char *c) {
634
+ rb_raise(rb_eRuntimeError, "%s", c);
635
+ }
636
+ return Wrap_bspline(cBspline, result);
637
+ }
638
+
639
+ static VALUE _wrap_bspline_mul(VALUE self, VALUE varg);
640
+
641
+ static void
642
+ _wrap_Init_bspline(void)
643
+ {
644
+ cBspline = rb_define_class_under(mPspline, "Bspline", rb_cObject);
645
+ rb_include_module(cBspline, rb_mEnumerable);
646
+ rb_define_singleton_method(cBspline, "new", VALUEFUNC(_wrap_new_bspline), -1);
647
+ rb_define_method(cBspline, "initialize", VALUEFUNC(_wrap_init_bspline), -1);
648
+ rb_define_method(cBspline, "[]", VALUEFUNC(_wrap_bspline_bracket), -1);
649
+ rb_define_method(cBspline, "value", VALUEFUNC(_wrap_bspline_value), -1);
650
+ rb_define_method(cBspline, "sekibun", VALUEFUNC(_wrap_bspline_sekibun), -1);
651
+ rb_define_method(cBspline, "plot", VALUEFUNC(_wrap_bspline_plot), -1);
652
+ rb_define_module_function(mPspline, "fft_complex_transform", VALUEFUNC(_wrap_complex_trans), 2);
653
+ rb_define_module_function(mPspline, "fft_complex_get", VALUEFUNC(_wrap_complex_get), 2);
654
+ rb_define_module_function(mPspline, "fft_real_transform", VALUEFUNC(_wrap_real_trans), 2);
655
+ rb_define_module_function(mPspline, "fft_real_get", VALUEFUNC(_wrap_real_get), 2);
656
+ rb_define_module_function(mPspline, "fft_complex_bspline", VALUEFUNC(_wrap_complex_bspline), 2);
657
+ rb_define_module_function(mPspline, "fft_real_bspline", VALUEFUNC(_wrap_real_bspline), 2);
658
+ rb_define_method(cBspline, "line_integral", VALUEFUNC(_wrap_bspline_lint), -1);
659
+ rb_define_method(cBspline, "*", VALUEFUNC(_wrap_bspline_mul), 1);
660
+ }
661
+
662
+ static VALUE cPspline;
663
+
664
+ static void Wrap_free_pspline(pspline<double> *arg0) { delete arg0; }
665
+
666
+ #define Wrap_pspline(klass, ptr) (\
667
+ (ptr) ? Data_Wrap_Struct(klass, 0, VOIDFUNC(Wrap_free_pspline), ptr) : Qnil )
668
+
669
+ #define Get_pspline(val, ptr) {\
670
+ if (NIL_P(val)) ptr = NULL;\
671
+ else {\
672
+ if (!rb_obj_is_kind_of(val, cPspline))\
673
+ rb_raise(rb_eTypeError, "wrong argument type (expected pspline)");\
674
+ Data_Get_Struct(val, pspline<double>, ptr);\
675
+ if (!ptr) rb_raise(rb_eRuntimeError, "This pspline already released");\
676
+ }\
677
+ }
678
+
679
+ // Pspline#new()
680
+
681
+ static VALUE
682
+ _wrap_new_pspline(int argc, VALUE *argv, VALUE klass)
683
+ {
684
+ VALUE self = Data_Wrap_Struct(klass, 0, VOIDFUNC(Wrap_free_pspline), 0);
685
+ rb_obj_call_init(self, argc, argv);
686
+ return self;
687
+ }
688
+
689
+ #define Get_param(N, varg, ptr, str) {\
690
+ Check_Type(varg, T_ARRAY);\
691
+ int k = RARRAY_LEN(varg);\
692
+ if (k != N)\
693
+ rb_raise(rb_eArgError, "%s list length = %d, it should be %d", str, k, N);\
694
+ ptr = ALLOC_N(int, k);\
695
+ for (int i = 0; i < k; ++i) ptr[i] = NUM2INT(RARRAY_PTR(varg)[i]);\
696
+ }
697
+
698
+ static comb_array<double> make_var(int N, VALUE var, int *n = NULL, int *m = NULL)
699
+ {
700
+ int M = 0, s[N+1]; VALUE vs[N];
701
+ for (int i = 0; i < N; ++i) {
702
+ vs[i] = RARRAY_PTR(var)[i];
703
+ Check_Type(vs[i], T_ARRAY);
704
+ s[i] = RARRAY_LEN(vs[i]);
705
+ if (n != NULL && m != NULL) {
706
+ int vars = n[i] + m[i]%2;
707
+ if (s[i] != vars)
708
+ rb_raise(rb_eArgError, "Elements = %d, it should be %d", s[i], vars);
709
+ }
710
+ M += s[i];
711
+ } s[N] = DTYPE;
712
+ Vector v(size_t(M), DTYPE); size_t p = 0;
713
+ for (int i = 0; i < N; ++i) {
714
+ for (int j = 0; j < s[i]; ++j) {
715
+ VALUE vv = RARRAY_PTR(vs[i])[j];
716
+ if (TYPE(vv) == T_STRING)
717
+ v[p + j] = StringValuePtr(vv);
718
+ else
719
+ v[p + j] = NUM2DBL(vv);
720
+ }
721
+ p += s[i];
722
+ }
723
+ return comb_array<double>((double*)v, N, s);
724
+ }
725
+
726
+ static VALUE make_flat(int K, VALUE val, int N, int *n)
727
+ {
728
+ if (N == 0) return val;
729
+ if (K != n[0]) rb_raise(rb_eArgError, "Wrong argument Array");
730
+ VALUE vals = rb_ary_new();
731
+ for (int i = 0; i < K; ++i) {
732
+ VALUE va = RARRAY_PTR(val)[i];
733
+ if (TYPE(va) == T_ARRAY) {
734
+ VALUE vb = rb_obj_dup(va);
735
+ vals = rb_ary_concat(vals, make_flat(RARRAY_LEN(va), vb, N-1, n+1));
736
+ }
737
+ else
738
+ rb_ary_push(vals, va);
739
+ }
740
+ return vals;
741
+ }
742
+
743
+ static poly_array<double> make_val(int &K, VALUE val, int N, int *n)
744
+ {
745
+ if (K != n[0]) rb_raise(rb_eArgError, "Member size = %d, it should be %d", K, n[0]);
746
+ VALUE vals = rb_ary_new();
747
+ for (int i = 0; i < K; ++i) {
748
+ VALUE va = RARRAY_PTR(val)[i];
749
+ if (TYPE(va) == T_ARRAY) {
750
+ VALUE vb = rb_obj_dup(va);
751
+ vals = rb_ary_concat(vals, make_flat(RARRAY_LEN(va), vb, N-1, n+1));
752
+ }
753
+ else
754
+ rb_ary_push(vals, va);
755
+ }
756
+ int M = RARRAY_LEN(vals);
757
+ K = M;
758
+ for (int i = 0; i < N; ++i) K /= n[i]; n[N] = K; n[N+1] = DTYPE;
759
+ Vector v(size_t(M), DTYPE);
760
+ for (int i = 0; i < M; ++i) {
761
+ VALUE vv = RARRAY_PTR(vals)[i];
762
+ if (TYPE(vv) == T_STRING)
763
+ v[i] = StringValuePtr(vv);
764
+ else
765
+ v[i] = NUM2DBL(vv);
766
+ }
767
+ return poly_array<double>((double*)v, N+1, n);
768
+ }
769
+ /*******************************************************************************
770
+ Calculate interpolation of N variable M dimension P-spline.
771
+ Pspline.new([X^Y^...], [S,T,...], N, J, S)
772
+ X^Y^...:点の座標
773
+ S,T,...:変数の座標
774
+ N:
775
+ J:スプライン次数(階数K=J+1)
776
+ S:
777
+ Result:P-spline object
778
+ *******************************************************************************/
779
+
780
+ // Pspline#initialize
781
+
782
+ static VALUE
783
+ _wrap_init_pspline(int argc, VALUE *argv, VALUE self)
784
+ {
785
+ VALUE vxyz, vstu, vargn, vargj, vargs;
786
+
787
+ int N, K, *n, *j, *s;
788
+
789
+ rb_scan_args(argc, argv, "5", &vxyz, &vstu, &vargn, &vargj, &vargs);
790
+
791
+ Check_Type(vstu, T_ARRAY);
792
+ N = RARRAY_LEN(vstu);
793
+
794
+ Get_param(N, vargs, s, "Type");
795
+
796
+ Get_param(N, vargj, j, "Degree");
797
+
798
+ Get_param(N, vargn, n, "Size");
799
+
800
+ Check_Type(vxyz, T_ARRAY);
801
+ K = RARRAY_LEN(vxyz);
802
+
803
+ try {
804
+
805
+ comb_array<double> stu = make_var(N, vstu, n, s);
806
+ poly_array<double> xyz = make_val(K, vxyz, N, n);
807
+
808
+ Int argn(N, n); argn = K;
809
+ // Int argj(N, j), args(N, s);
810
+ // argn.print("%d, "); argj.print("%d, "); args.print("%d\n");
811
+ // stu.print("%g\n"); xyz.print("%g\n");
812
+ DATA_PTR(self) = new pspline<double>(xyz, stu, argn, j, s);
813
+
814
+ } catch (const char *c) {
815
+ rb_raise(rb_eRuntimeError, "%s", c);
816
+ }
817
+ free(n);
818
+ free(j);
819
+ free(s);
820
+ return self;
821
+ }
822
+ /*******************************************************************************
823
+ 関数値
824
+
825
+ pspline#[x[, ...]]
826
+ x:点のX座標(数値,または数値の配列)
827
+
828
+ Result:補間値
829
+ *******************************************************************************/
830
+ static VALUE
831
+ _wrap_pspline_bracket(int argc, VALUE *argv, VALUE self)
832
+ {
833
+ pspline<double> *bsp;
834
+ VALUE vargs, vresult, mresult = Qnil;
835
+ char *fmt = NULL, *num;
836
+
837
+ Get_pspline(self, bsp);
838
+ int N = bsp->Grid();
839
+ int K = bsp->Unit();
840
+ mresult = rb_ary_new();
841
+ try {
842
+ for (int m = 0; m < argc; ++m) {
843
+ vargs = argv[m];
844
+ Vector val;
845
+ if (TYPE(vargs) == T_STRING) {
846
+ num = StringValuePtr(vargs);
847
+ char *c = num;
848
+ if (*c == '%') { ++c;
849
+ while (*c >= '0' && *c <= '9' || *c == '.') ++c;
850
+ if (*c >= 'e' && *c <= 'g') {
851
+ fmt = num;
852
+ continue;
853
+ }
854
+ }
855
+ val = (*bsp)[Real(num, DTYPE)];
856
+ } else if (TYPE(vargs) == T_ARRAY) {
857
+ int L = RARRAY_LEN(vargs);
858
+ if (L != N)
859
+ rb_raise(rb_eArgError, "Array length = %d, it should be %d.", L, N);
860
+ Vector args(size_t(N), DTYPE);
861
+ for (int i = 0; i < N; ++i) {
862
+ VALUE vv = RARRAY_PTR(vargs)[i];
863
+ if (TYPE(vv) == T_STRING)
864
+ args[i] = StringValuePtr(vv);
865
+ else
866
+ args[i] = NUM2DBL(vv);
867
+ }
868
+ val = (*bsp)[args];
869
+ } else
870
+ val = (*bsp)[Real(NUM2DBL(vargs), DTYPE)];
871
+ if (K == 1) {
872
+ if (fmt)
873
+ vresult = rb_str_new2(val[0].to_s(fmt));
874
+ else
875
+ vresult = rb_float_new(val[0](0));
876
+ } else {
877
+ vresult = rb_ary_new();
878
+ for (int j = 0; j < K; ++j)
879
+ if (fmt)
880
+ rb_ary_push(vresult, rb_str_new2(val[j].to_s(fmt)));
881
+ else
882
+ rb_ary_push(vresult, rb_float_new(val[j](0)));
883
+ }
884
+ rb_ary_push(mresult, vresult);
885
+ }
886
+ } catch (const char *c) {
887
+ rb_raise(rb_eRuntimeError, "%s", c);
888
+ }
889
+ return argc == 1 ? rb_ary_shift(mresult) : mresult;
890
+ }
891
+
892
+ void ps_eArgError(VALUE err)
893
+ {
894
+ VALUE str = rb_String(err);
895
+ rb_raise(rb_eArgError, "wrong argument %s", StringValuePtr(str));
896
+ }
897
+ /*******************************************************************************
898
+ 関数値
899
+ pspline#value(x, d = 0)
900
+ x:点のX座標
901
+ d:微分階数(省略可)
902
+ Result:補間値,または微分値
903
+ *******************************************************************************/
904
+ static VALUE
905
+ _wrap_pspline_value(int argc, VALUE *argv, VALUE self)
906
+ {
907
+ VALUE varg1, varg2, varg3, varg4;
908
+ pspline<double> *arg0;
909
+ int argn, arg2 = 0;
910
+ VALUE vargs, vresult = Qnil;
911
+ char *fmt = NULL, *num;
912
+
913
+ rb_scan_args(argc, argv, "22", &varg1, &varg2, &varg3);
914
+
915
+ if (TYPE(varg1) == T_STRING) {
916
+ num = StringValuePtr(varg1);
917
+ char *c = num;
918
+ if (*c == '%') { ++c;
919
+ while ((*c >= '0' && *c <= '9') || *c == '.') ++c;
920
+ if (*c >= 'e' && *c <= 'g') {
921
+ fmt = num;
922
+ varg1 = varg2;
923
+ if (argc > 2) varg2 = varg3;
924
+ if (argc > 3) varg3 = varg4;
925
+ argc--;
926
+ }
927
+ }
928
+ }
929
+
930
+ Get_pspline(self, arg0);
931
+ int N = arg0->Grid();
932
+ int K = arg0->Unit();
933
+ // 全微分
934
+ Vector carg3;
935
+ if (argc == 3) {
936
+ arg2 = NUM2INT(varg2);
937
+ carg3 = Vector(size_t(N), DTYPE);
938
+ Check_Type(varg3, T_ARRAY);
939
+ if (RARRAY_LEN(varg3) != N) ps_eArgError(varg3);
940
+ for (int i = 0; i < N; ++i) {
941
+ VALUE vv = RARRAY_PTR(varg3)[i];
942
+ if (TYPE(vv) == T_STRING)
943
+ carg3[i] = StringValuePtr(vv);
944
+ else
945
+ carg3[i] = NUM2DBL(vv);
946
+ }
947
+ }
948
+ // 偏微分
949
+ int *carg2 = NULL;
950
+ if (argc == 2) {
951
+ if (TYPE(varg2) == T_ARRAY && RARRAY_LEN(varg2) == N) {
952
+ carg2 = new int[N];
953
+ for (int i = 0; i < N; ++i)
954
+ carg2[i] = NUM2INT(RARRAY_PTR(varg2)[i]);
955
+ } else if (TYPE(varg1) != T_ARRAY) {
956
+ arg2 = NUM2INT(varg2);
957
+ argc = arg2 ? 0 : 1;
958
+ } else ps_eArgError(varg2);
959
+ }
960
+ // Argument list
961
+ Vector arg; Real arg1((size_t)DTYPE);
962
+ bool argf = false;
963
+ if (TYPE(varg1) == T_ARRAY) {
964
+ argn = RARRAY_LEN(varg1);
965
+ vargs = make_list(argn, RARRAY_PTR(varg1));
966
+ argn = RARRAY_LEN(vargs);
967
+ if (argn == N) {
968
+ arg = Vector(size_t(N), DTYPE); argf = true;
969
+ for (int i = 0; i < N; ++i) {
970
+ VALUE vv = RARRAY_PTR(vargs)[i];
971
+ if (TYPE(vv) == T_STRING)
972
+ arg[i] = StringValuePtr(vv);
973
+ else
974
+ arg[i] = NUM2DBL(vv);
975
+ }
976
+ } else ps_eArgError(varg1);
977
+ } else
978
+ if (argc <= 1) {
979
+ if (TYPE(varg1) == T_STRING)
980
+ arg1 = StringValuePtr(varg1);
981
+ else
982
+ arg1 = NUM2DBL(varg1);
983
+ } else ps_eArgError(varg1);
984
+ if (argc < 2) argc ^= 1;
985
+ Vector val;
986
+ try {
987
+ /* printf("argc = %d, ", argc); if (argc%2) printf("arg2 = %d\n", arg2);
988
+ if (argf) arg.print("arg = %g\n"); else arg1.print("arg1 = %g\n");
989
+ if (argc == 2) {
990
+ printf("carg2 = [");
991
+ for (int i= 0; i < N; ++i) {
992
+ printf("%d", carg2[i]); if (i < N-1) printf(", ");
993
+ } printf("]\n");
994
+ }
995
+ if (argc == 3) carg3.print("carg3 = %g\n");
996
+ */ switch (argc) {
997
+ case 0: // 関数値(関数積を含む)
998
+ val = argf ? (*arg0)(arg) : (*arg0)(arg1);
999
+ break;
1000
+ case 1: // 関数積の微分
1001
+ val = (*arg0)(arg1, arg2);
1002
+ break;
1003
+ case 2: // 偏微分 (partial derivative)
1004
+ val = (*arg0)(arg, carg2);
1005
+ break;
1006
+ case 3: // 全微分 (total derivative)
1007
+ val = (*arg0)(arg, arg2, carg3);
1008
+ } delete[] carg2;
1009
+ } catch (const char *c) {
1010
+ rb_raise(rb_eRuntimeError, "%s", c);
1011
+ }
1012
+ if (K == 1) {
1013
+ if (fmt)
1014
+ vresult = rb_str_new2(val[0].to_s(fmt));
1015
+ else
1016
+ vresult = rb_float_new(val[0](0));
1017
+ } else {
1018
+ vresult = rb_ary_new();
1019
+ for (int j = 0; j < K; ++j)
1020
+ if (fmt)
1021
+ rb_ary_push(vresult, rb_str_new2(val[j].to_s(fmt)));
1022
+ else
1023
+ rb_ary_push(vresult, rb_float_new(val[j](0)));
1024
+ }
1025
+ return vresult;
1026
+ }
1027
+
1028
+ static VALUE
1029
+ _wrap_pspline_sekibun(int argc, VALUE *argv, VALUE self)
1030
+ {
1031
+ pspline<double> *bsp;
1032
+ VALUE vargs, vresult = Qnil;
1033
+ char *fmt = NULL, *num;
1034
+
1035
+ Get_pspline(self, bsp);
1036
+ int N = bsp->Grid();
1037
+ int K = bsp->Unit();
1038
+
1039
+ VALUE * argw = argv;
1040
+ if (TYPE(argv[0]) == T_STRING) {
1041
+ num = StringValuePtr(argv[0]);
1042
+ char *c = num;
1043
+ if (*c == '%') { ++c;
1044
+ while ((*c >= '0' && *c <= '9') || *c == '.') ++c;
1045
+ if (*c >= 'e' && *c <= 'g') {
1046
+ fmt = num;
1047
+ argw++;
1048
+ argc--;
1049
+ }
1050
+ }
1051
+ }
1052
+
1053
+ vargs = make_list(argc, argw);
1054
+ argc = RARRAY_LEN(vargs);
1055
+ if (argc == N || argc == 1) {
1056
+ try {
1057
+ Vector args(size_t(N), DTYPE);
1058
+ for (int i = 0; i < N; ++i)
1059
+ if (i == 0 || argc == N) {
1060
+ VALUE vv = RARRAY_PTR(vargs)[i];
1061
+ if (TYPE(vv) == T_STRING)
1062
+ args[i] = StringValuePtr(vv);
1063
+ else
1064
+ args[i] = NUM2DBL(vv);
1065
+ } else
1066
+ args[i] = args[i-1];
1067
+ Vector val = bsp->sekibun(0, args);
1068
+ if (K == 1) {
1069
+ if (fmt)
1070
+ vresult = rb_str_new2(val[0].to_s(fmt));
1071
+ else
1072
+ vresult = rb_float_new(val[0](0));
1073
+ } else {
1074
+ vresult = rb_ary_new();
1075
+ for (int j = 0; j < K; ++j) {
1076
+ if (fmt)
1077
+ rb_ary_push(vresult, rb_str_new2(val[j].to_s(fmt)));
1078
+ else
1079
+ rb_ary_push(vresult, rb_float_new(val[j](0)));
1080
+ }
1081
+ }
1082
+ } catch (const char *c) {
1083
+ rb_raise(rb_eRuntimeError, "%s", c);
1084
+ }
1085
+ } else rb_raise(rb_eArgError, "wrong argument Sekibun");
1086
+ return vresult;
1087
+ }
1088
+
1089
+ static VALUE
1090
+ _wrap_pspline_plot(int argc, VALUE *argv, VALUE self)
1091
+ {
1092
+ pspline<double> *arg0;
1093
+ VALUE vstu, varg, vdp, vjbn;
1094
+ int arg3, *arg4 = NULL;
1095
+
1096
+ rb_scan_args(argc, argv, "21", &varg, &vdp, &vjbn);
1097
+
1098
+ Get_pspline(self, arg0);
1099
+ int N = arg0->Grid();
1100
+ int K = arg0->Unit();
1101
+ arg3 = NUM2INT(vdp);
1102
+ if (argc > 2) {
1103
+ arg4 = new int[N];
1104
+ if (TYPE(vjbn) == T_ARRAY) {
1105
+ int n = RARRAY_LEN(vjbn);
1106
+ if (n != N)
1107
+ rb_raise(rb_eArgError, "Differential orders = %d, it should be %d", n, N);
1108
+ for (int i = 0; i < N; ++i)
1109
+ arg4[i] = NUM2INT(RARRAY_PTR(vjbn)[i]);
1110
+ } else
1111
+ arg4[0] = NUM2INT(vjbn);
1112
+ }
1113
+ Check_Type(varg, T_ARRAY);
1114
+ N = RARRAY_LEN(varg);
1115
+ vstu = rb_ary_new();
1116
+ int result;
1117
+ for (int i = 0; i < N; ++i) rb_ary_push(vstu, rb_ary_shift(varg));
1118
+ Matrix arg1, arg2; Vector arg5;
1119
+ try {
1120
+ if (TYPE(RARRAY_PTR(vstu)[0]) == T_ARRAY) {
1121
+ comb_array<double> stu = make_var(N, vstu);
1122
+ result = plot<double>(*arg0, stu, arg1, arg2, arg3, arg4);
1123
+ } else {
1124
+ Vector x(size_t(N), DTYPE);
1125
+ for (int i = 0; i < N; i++) x[i] = NUM2DBL(RARRAY_PTR(vstu)[i]);
1126
+ result = plot<double>(*arg0, N, x, arg5, arg2, arg3, arg4[0]);
1127
+ N = 1;
1128
+ arg1 = Matrix(size_t(result), size_t(N), DTYPE, (double*)arg5);
1129
+ }
1130
+ } catch (const char *c) {
1131
+ rb_raise(rb_eRuntimeError, "%s", c);
1132
+ }
1133
+ delete[] arg4;
1134
+ for (int i = 0; i < result; i++) {
1135
+ VALUE v1 = rb_ary_new();
1136
+ for (int j = 0; j < N; ++j) rb_ary_push(v1, rb_float_new(arg1[i][j](0)));
1137
+ VALUE v2 = rb_ary_new();
1138
+ for (int k = 0; k < K; ++k) rb_ary_push(v2, rb_float_new(arg2[i][k](0)));
1139
+ VALUE vv = rb_ary_new();
1140
+ rb_ary_push(vv, v1);
1141
+ rb_ary_push(vv, v2);
1142
+ rb_ary_push(varg, vv);
1143
+ if (rb_block_given_p()) rb_yield(vv);
1144
+ }
1145
+ return INT2NUM(result);
1146
+ }
1147
+
1148
+ static VALUE
1149
+ _wrap_bspline_mul(VALUE self, VALUE varg)
1150
+ {
1151
+ bspline<double> *arg0;
1152
+ Get_bspline(self, arg0);
1153
+ pspline<double> *result;
1154
+ if (rb_obj_is_kind_of(varg, cBspline)) {
1155
+ bspline<double> *arg1;
1156
+ Data_Get_Struct(varg, bspline<double>, arg1);
1157
+ if (!arg1) rb_raise(rb_eArgError, "Not Bspline object");
1158
+ result = new pspline<double>((*arg0) * (*arg1));
1159
+ } else if (rb_obj_is_kind_of(varg, cPspline)) {
1160
+ pspline<double> *arg1;
1161
+ Data_Get_Struct(varg, pspline<double>, arg1);
1162
+ if (!arg1) rb_raise(rb_eArgError, "Not Pspline Object");
1163
+ result = new pspline<double>((*arg0) * (*arg1));
1164
+ } else {
1165
+ double a = NUM2DBL(varg);
1166
+ bspline<double> *result = new bspline<double>(*arg0);
1167
+ Matrix *p = *result;
1168
+ int k = result->Unit();
1169
+ int c = result->Icox();
1170
+ for (int i = 0; i < c; i++)
1171
+ for (int j = 0; j < k; ++j)
1172
+ p[i][j] *= a;
1173
+ return Wrap_bspline(cBspline, result);
1174
+ }
1175
+ return Wrap_pspline(cPspline, result);
1176
+ }
1177
+
1178
+ static VALUE
1179
+ _wrap_pspline_mul(VALUE self, VALUE varg)
1180
+ {
1181
+ pspline<double> *arg0;
1182
+ Get_pspline(self, arg0);
1183
+ pspline<double> *result;
1184
+ if (rb_obj_is_kind_of(varg, cBspline)) {
1185
+ bspline<double> *arg1;
1186
+ Data_Get_Struct(varg, bspline<double>, arg1);
1187
+ if (!arg1) rb_raise(rb_eArgError, "Not Bspline object");
1188
+ result = new pspline<double>((*arg0) * (*arg1));
1189
+ }/* else if (rb_obj_is_kind_of(varg, cPspline)) {
1190
+ pspline<double> *arg1;
1191
+ Data_Get_Struct(varg, pspline<double>, arg1);
1192
+ if (!arg1) rb_raise(rb_eArgError, "Not Pspline object");
1193
+ result = new pspline<double>((*arg0) * (*arg1));
1194
+ }*/ else {
1195
+ double a = NUM2DBL(varg);
1196
+ result = new pspline<double>(*arg0);
1197
+ Matrix *p = *result;
1198
+ int c = p->rows();
1199
+ int k = p->cols();
1200
+ for (int i = 0; i < c; i++)
1201
+ for (int j = 0; j < k; ++j)
1202
+ p[i][j] *= a;
1203
+ }
1204
+ return Wrap_pspline(cPspline, result);
1205
+ }
1206
+
1207
+ static void
1208
+ _wrap_Init_pspline(void)
1209
+ {
1210
+ cPspline = rb_define_class_under(mPspline, "Pspline", rb_cObject);
1211
+ rb_include_module(cPspline, rb_mEnumerable);
1212
+ rb_define_singleton_method(cPspline, "new", VALUEFUNC(_wrap_new_pspline), -1);
1213
+ rb_define_method(cPspline, "initialize", VALUEFUNC(_wrap_init_pspline), -1);
1214
+ rb_define_method(cPspline, "[]", VALUEFUNC(_wrap_pspline_bracket), -1);
1215
+ rb_define_method(cPspline, "value", VALUEFUNC(_wrap_pspline_value), -1);
1216
+ rb_define_method(cPspline, "sekibun", VALUEFUNC(_wrap_pspline_sekibun), -1);
1217
+ rb_define_method(cPspline, "plot", VALUEFUNC(_wrap_pspline_plot), -1);
1218
+ // rb_define_method(cPspline, "*", VALUEFUNC(_wrap_pspline_mul), 1);
1219
+ }
1220
+
1221
+ #ifdef __cplusplus
1222
+ extern "C" {
1223
+ #endif
1224
+
1225
+ void Init_pspline(void)
1226
+ {
1227
+ mPspline = rb_define_module("PSPLINE");
1228
+
1229
+ _wrap_Init_bspline();
1230
+ _wrap_Init_pspline();
1231
+ }
1232
+
1233
+ #ifdef __cplusplus
1234
+ }
1235
+ #endif
1236
+