gsl 1.12.108

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. data/README.rdoc +29 -0
  2. data/Rakefile +54 -0
  3. data/VERSION +2 -0
  4. data/ext/MANIFEST +119 -0
  5. data/ext/alf.c +206 -0
  6. data/ext/array.c +666 -0
  7. data/ext/array_complex.c +247 -0
  8. data/ext/blas.c +29 -0
  9. data/ext/blas1.c +731 -0
  10. data/ext/blas2.c +1093 -0
  11. data/ext/blas3.c +881 -0
  12. data/ext/block.c +44 -0
  13. data/ext/block_source.c +886 -0
  14. data/ext/bspline.c +130 -0
  15. data/ext/bundle.c +3 -0
  16. data/ext/cdf.c +754 -0
  17. data/ext/cheb.c +542 -0
  18. data/ext/combination.c +283 -0
  19. data/ext/common.c +325 -0
  20. data/ext/complex.c +1004 -0
  21. data/ext/const.c +673 -0
  22. data/ext/const_additional.c +120 -0
  23. data/ext/cqp.c +283 -0
  24. data/ext/deriv.c +195 -0
  25. data/ext/dht.c +361 -0
  26. data/ext/diff.c +166 -0
  27. data/ext/dirac.c +395 -0
  28. data/ext/eigen.c +2373 -0
  29. data/ext/error.c +194 -0
  30. data/ext/extconf.rb +281 -0
  31. data/ext/fcmp.c +66 -0
  32. data/ext/fft.c +1092 -0
  33. data/ext/fit.c +205 -0
  34. data/ext/fresnel.c +312 -0
  35. data/ext/function.c +524 -0
  36. data/ext/geometry.c +139 -0
  37. data/ext/graph.c +1638 -0
  38. data/ext/gsl.c +271 -0
  39. data/ext/gsl_narray.c +653 -0
  40. data/ext/histogram.c +1995 -0
  41. data/ext/histogram2d.c +1068 -0
  42. data/ext/histogram3d.c +884 -0
  43. data/ext/histogram3d_source.c +750 -0
  44. data/ext/histogram_find.c +101 -0
  45. data/ext/histogram_oper.c +159 -0
  46. data/ext/ieee.c +98 -0
  47. data/ext/integration.c +1138 -0
  48. data/ext/interp.c +512 -0
  49. data/ext/jacobi.c +739 -0
  50. data/ext/linalg.c +4047 -0
  51. data/ext/linalg_complex.c +741 -0
  52. data/ext/math.c +725 -0
  53. data/ext/matrix.c +39 -0
  54. data/ext/matrix_complex.c +1732 -0
  55. data/ext/matrix_double.c +560 -0
  56. data/ext/matrix_int.c +256 -0
  57. data/ext/matrix_source.c +2733 -0
  58. data/ext/min.c +250 -0
  59. data/ext/monte.c +992 -0
  60. data/ext/multifit.c +1879 -0
  61. data/ext/multimin.c +808 -0
  62. data/ext/multimin_fsdf.c +156 -0
  63. data/ext/multiroots.c +955 -0
  64. data/ext/ndlinear.c +321 -0
  65. data/ext/nmf.c +167 -0
  66. data/ext/nmf_wrap.c +72 -0
  67. data/ext/ntuple.c +469 -0
  68. data/ext/odeiv.c +959 -0
  69. data/ext/ool.c +879 -0
  70. data/ext/oper_complex_source.c +253 -0
  71. data/ext/permutation.c +596 -0
  72. data/ext/poly.c +42 -0
  73. data/ext/poly2.c +265 -0
  74. data/ext/poly_source.c +1885 -0
  75. data/ext/qrng.c +171 -0
  76. data/ext/randist.c +1873 -0
  77. data/ext/rational.c +480 -0
  78. data/ext/rng.c +612 -0
  79. data/ext/root.c +408 -0
  80. data/ext/sf.c +1494 -0
  81. data/ext/sf_airy.c +200 -0
  82. data/ext/sf_bessel.c +867 -0
  83. data/ext/sf_clausen.c +28 -0
  84. data/ext/sf_coulomb.c +206 -0
  85. data/ext/sf_coupling.c +118 -0
  86. data/ext/sf_dawson.c +29 -0
  87. data/ext/sf_debye.c +157 -0
  88. data/ext/sf_dilog.c +42 -0
  89. data/ext/sf_elementary.c +44 -0
  90. data/ext/sf_ellint.c +206 -0
  91. data/ext/sf_elljac.c +29 -0
  92. data/ext/sf_erfc.c +93 -0
  93. data/ext/sf_exp.c +164 -0
  94. data/ext/sf_expint.c +211 -0
  95. data/ext/sf_fermi_dirac.c +148 -0
  96. data/ext/sf_gamma.c +344 -0
  97. data/ext/sf_gegenbauer.c +96 -0
  98. data/ext/sf_hyperg.c +197 -0
  99. data/ext/sf_laguerre.c +112 -0
  100. data/ext/sf_lambert.c +47 -0
  101. data/ext/sf_legendre.c +367 -0
  102. data/ext/sf_log.c +104 -0
  103. data/ext/sf_mathieu.c +238 -0
  104. data/ext/sf_power.c +46 -0
  105. data/ext/sf_psi.c +98 -0
  106. data/ext/sf_synchrotron.c +48 -0
  107. data/ext/sf_transport.c +76 -0
  108. data/ext/sf_trigonometric.c +207 -0
  109. data/ext/sf_zeta.c +119 -0
  110. data/ext/signal.c +310 -0
  111. data/ext/siman.c +718 -0
  112. data/ext/sort.c +208 -0
  113. data/ext/spline.c +395 -0
  114. data/ext/stats.c +799 -0
  115. data/ext/sum.c +168 -0
  116. data/ext/tamu_anova.c +56 -0
  117. data/ext/tensor.c +38 -0
  118. data/ext/tensor_source.c +1123 -0
  119. data/ext/vector.c +38 -0
  120. data/ext/vector_complex.c +2236 -0
  121. data/ext/vector_double.c +1433 -0
  122. data/ext/vector_int.c +204 -0
  123. data/ext/vector_source.c +3329 -0
  124. data/ext/wavelet.c +937 -0
  125. data/include/rb_gsl.h +151 -0
  126. data/include/rb_gsl_array.h +238 -0
  127. data/include/rb_gsl_cheb.h +21 -0
  128. data/include/rb_gsl_common.h +343 -0
  129. data/include/rb_gsl_complex.h +25 -0
  130. data/include/rb_gsl_const.h +29 -0
  131. data/include/rb_gsl_dirac.h +13 -0
  132. data/include/rb_gsl_eigen.h +17 -0
  133. data/include/rb_gsl_fft.h +62 -0
  134. data/include/rb_gsl_fit.h +25 -0
  135. data/include/rb_gsl_function.h +27 -0
  136. data/include/rb_gsl_graph.h +70 -0
  137. data/include/rb_gsl_histogram.h +63 -0
  138. data/include/rb_gsl_histogram3d.h +97 -0
  139. data/include/rb_gsl_integration.h +17 -0
  140. data/include/rb_gsl_interp.h +46 -0
  141. data/include/rb_gsl_linalg.h +25 -0
  142. data/include/rb_gsl_math.h +26 -0
  143. data/include/rb_gsl_odeiv.h +21 -0
  144. data/include/rb_gsl_poly.h +71 -0
  145. data/include/rb_gsl_rational.h +37 -0
  146. data/include/rb_gsl_rng.h +21 -0
  147. data/include/rb_gsl_root.h +22 -0
  148. data/include/rb_gsl_sf.h +119 -0
  149. data/include/rb_gsl_statistics.h +17 -0
  150. data/include/rb_gsl_tensor.h +45 -0
  151. data/include/rb_gsl_with_narray.h +22 -0
  152. data/include/templates_off.h +87 -0
  153. data/include/templates_on.h +241 -0
  154. data/lib/gsl/gnuplot.rb +41 -0
  155. data/lib/gsl/oper.rb +68 -0
  156. data/lib/ool.rb +22 -0
  157. data/lib/ool/conmin.rb +30 -0
  158. metadata +224 -0
@@ -0,0 +1,66 @@
1
+ /* sys/gsl_compare.c
2
+ *
3
+ * Copyright (C) 2002 Gert Van den Eynde
4
+ *
5
+ * This program is free software; you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License as published by
7
+ * the Free Software Foundation; either version 2 of the License, or (at
8
+ * your option) any later version.
9
+ *
10
+ * This program is distributed in the hope that it will be useful, but
11
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with this program; if not, write to the Free Software
17
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
+ *
19
+ * Based on fcmp 1.2.2 Copyright (c) 1998-2000 Theodore C. Belding
20
+ * University of Michigan Center for the Study of Complex Systems
21
+ * Ted.Belding@umich.edu
22
+ *
23
+ */
24
+
25
+ #include "rb_gsl_config.h"
26
+
27
+ #ifndef GSL_1_3_LATER
28
+
29
+ #include <config.h>
30
+ #include <gsl/gsl_sys.h>
31
+ #include <math.h>
32
+
33
+ int gsl_fcmp(const double x1, const double x2, const double epsilon)
34
+ {
35
+ int exponent;
36
+ double delta, difference;
37
+
38
+ /* Find exponent of largest absolute value */
39
+
40
+ {
41
+ double max = (fabs (x1) > fabs (x2)) ? x1 : x2;
42
+
43
+ frexp (max, &exponent);
44
+ }
45
+
46
+ /* Form a neighborhood of size 2 * delta */
47
+
48
+ delta = ldexp (epsilon, exponent);
49
+
50
+ difference = x1 - x2;
51
+
52
+ if (difference > delta) /* x1 > x2 */
53
+ {
54
+ return 1;
55
+ }
56
+ else if (difference < -delta) /* x1 < x2 */
57
+ {
58
+ return -1;
59
+ }
60
+ else /* -delta <= difference <= delta */
61
+ {
62
+ return 0; /* x1 ~=~ x2 */
63
+ }
64
+ }
65
+
66
+ #endif
@@ -0,0 +1,1092 @@
1
+ /*
2
+ fft.c
3
+ Ruby/GSL: Ruby extension library for GSL (GNU Scientific Library)
4
+ (C) Copyright 2004 by Yoshiki Tsunesada
5
+
6
+ Ruby/GSL is free software: you can redistribute it and/or modify it
7
+ under the terms of the GNU General Public License.
8
+ This library is distributed in the hope that it will be useful, but
9
+ WITHOUT ANY WARRANTY.
10
+ */
11
+
12
+ #include "rb_gsl_config.h"
13
+ #include "rb_gsl_fft.h"
14
+
15
+ VALUE mgsl_fft;
16
+ VALUE cgsl_fft_wavetable;
17
+ VALUE cgsl_fft_complex_wavetable, cgsl_fft_complex_workspace;
18
+ VALUE cgsl_fft_real_wavetable, cgsl_fft_halfcomplex_wavetable;
19
+ VALUE cgsl_fft_real_workspace;
20
+
21
+ extern VALUE cgsl_vector_int;
22
+ extern VALUE cgsl_vector_complex;
23
+
24
+ static void GSL_FFT_Workspace_free(GSL_FFT_Workspace *space);
25
+
26
+ static VALUE rb_gsl_fft_complex_wavetable_new(VALUE klass, VALUE n)
27
+ {
28
+ CHECK_FIXNUM(n);
29
+ return Data_Wrap_Struct(cgsl_fft_complex_wavetable, 0,
30
+ gsl_fft_complex_wavetable_free,
31
+ gsl_fft_complex_wavetable_alloc(FIX2INT(n)));
32
+ }
33
+
34
+ static VALUE rb_gsl_fft_real_wavetable_new(VALUE klass, VALUE n)
35
+ {
36
+ CHECK_FIXNUM(n);
37
+ return Data_Wrap_Struct(klass, 0, gsl_fft_real_wavetable_free,
38
+ gsl_fft_real_wavetable_alloc(FIX2INT(n)));
39
+ }
40
+
41
+ static VALUE rb_gsl_fft_halfcomplex_wavetable_new(VALUE klass, VALUE n)
42
+ {
43
+ CHECK_FIXNUM(n);
44
+ return Data_Wrap_Struct(klass, 0, gsl_fft_halfcomplex_wavetable_free,
45
+ gsl_fft_halfcomplex_wavetable_alloc(FIX2INT(n)));
46
+
47
+ }
48
+
49
+ static void GSL_FFT_Wavetable_free(GSL_FFT_Wavetable *table)
50
+ {
51
+ gsl_fft_complex_wavetable_free((gsl_fft_complex_wavetable *) table);
52
+ }
53
+
54
+ static VALUE rb_gsl_fft_complex_workspace_new(VALUE klass, VALUE n)
55
+ {
56
+ CHECK_FIXNUM(n);
57
+ return Data_Wrap_Struct(klass, 0, gsl_fft_complex_workspace_free,
58
+ gsl_fft_complex_workspace_alloc(FIX2INT(n)));
59
+ }
60
+
61
+ static VALUE rb_gsl_fft_real_workspace_new(VALUE klass, VALUE n)
62
+ {
63
+ CHECK_FIXNUM(n);
64
+ return Data_Wrap_Struct(klass, 0, gsl_fft_real_workspace_free,
65
+ gsl_fft_real_workspace_alloc(FIX2INT(n)));
66
+ }
67
+
68
+ static void GSL_FFT_Workspace_free(GSL_FFT_Workspace *space)
69
+ {
70
+ gsl_fft_complex_workspace_free((gsl_fft_complex_workspace *) space);
71
+ }
72
+
73
+ // The FFT methods used to allow passing stride and n values as optional
74
+ // parameters to control which elements get transformed. This created problems
75
+ // for Views which can have their own stride, so support for stride and n
76
+ // parameters to the transform methods is being dropped. This method used to
77
+ // be called to determine the stride and n values to use based on the
78
+ // parameters and/or the vector itself (depending on how many parameters were
79
+ // passed). Now this function is somewhat unneceesary, but to simplify the code
80
+ // refactoring, it has been left in place for the time being. Eventually it
81
+ // can be refactored away completely.
82
+ static VALUE get_complex_stride_n(VALUE obj,
83
+ gsl_vector_complex **vin,
84
+ gsl_complex_packed_array *data, size_t *stride, size_t *n)
85
+ {
86
+ gsl_vector_complex *v = NULL;
87
+
88
+ // obj must be a GSL::Vector::Complex
89
+ CHECK_VECTOR_COMPLEX(obj);
90
+ Data_Get_Struct(obj, gsl_vector_complex, v);
91
+
92
+ if(vin) *vin = v;
93
+ *data = (gsl_complex_packed_array) v->data;
94
+ *stride = v->stride;
95
+ *n = v->size;
96
+ return obj;
97
+ }
98
+
99
+ static VALUE rb_fft_complex_radix2(VALUE obj,
100
+ int (*trans)(gsl_complex_packed_array,
101
+ size_t, size_t), int flag)
102
+ {
103
+ size_t stride, n;
104
+ gsl_complex_packed_array data;
105
+ gsl_vector_complex *vin, *vout;
106
+ VALUE ary;
107
+ ary = get_complex_stride_n(obj, &vin, &data, &stride, &n);
108
+ if (flag == RB_GSL_FFT_COPY) {
109
+ vout = gsl_vector_complex_alloc(n);
110
+ gsl_vector_complex_memcpy(vout, vin);
111
+ (*trans)(vout->data, vout->stride /*1*/, vout->size /*n*/);
112
+ return Data_Wrap_Struct(cgsl_vector_complex, 0, gsl_vector_complex_free, vout);
113
+ } else { /* in-place */
114
+ (*trans)(data, stride, n);
115
+ return ary;
116
+ }
117
+ }
118
+
119
+ static VALUE rb_gsl_fft_complex_radix2_forward(VALUE obj)
120
+ {
121
+ return rb_fft_complex_radix2(obj, gsl_fft_complex_radix2_forward,
122
+ RB_GSL_FFT_COPY);
123
+ }
124
+
125
+ static VALUE rb_gsl_fft_complex_radix2_forward2(VALUE obj)
126
+ {
127
+ return rb_fft_complex_radix2(obj, gsl_fft_complex_radix2_forward,
128
+ RB_GSL_FFT_INPLACE);
129
+ }
130
+
131
+ static VALUE rb_gsl_fft_complex_radix2_transform(VALUE obj, VALUE val_sign)
132
+ {
133
+ size_t stride, n;
134
+ gsl_complex_packed_array data;
135
+ gsl_fft_direction sign;
136
+ gsl_vector_complex *vin, *vout;
137
+ sign = NUM2INT(val_sign);
138
+ get_complex_stride_n(obj, &vin, &data, &stride, &n);
139
+ vout = gsl_vector_complex_alloc(n);
140
+ gsl_vector_complex_memcpy(vout, vin);
141
+ gsl_fft_complex_radix2_transform(vout->data, vout->stride /*1*/, vout->size /*n*/, sign);
142
+ return Data_Wrap_Struct(cgsl_vector_complex, 0, gsl_vector_complex_free, vout);
143
+ }
144
+
145
+ static VALUE rb_gsl_fft_complex_radix2_transform2(VALUE obj, VALUE val_sign)
146
+ {
147
+ size_t stride, n;
148
+ gsl_complex_packed_array data;
149
+ gsl_fft_direction sign;
150
+ VALUE ary;
151
+ sign = NUM2INT(val_sign);
152
+ ary = get_complex_stride_n(obj, NULL, &data, &stride, &n);
153
+ gsl_fft_complex_radix2_transform(data, stride, n, sign);
154
+ return ary;
155
+ }
156
+
157
+ static VALUE rb_gsl_fft_complex_radix2_backward(VALUE obj)
158
+ {
159
+ return rb_fft_complex_radix2(obj, gsl_fft_complex_radix2_backward,
160
+ RB_GSL_FFT_COPY);
161
+ }
162
+
163
+ static VALUE rb_gsl_fft_complex_radix2_inverse(VALUE obj)
164
+ {
165
+ return rb_fft_complex_radix2(obj, gsl_fft_complex_radix2_inverse,
166
+ RB_GSL_FFT_COPY);
167
+ }
168
+
169
+ static VALUE rb_gsl_fft_complex_radix2_dif_forward(VALUE obj)
170
+ {
171
+ return rb_fft_complex_radix2(obj,
172
+ gsl_fft_complex_radix2_dif_forward,
173
+ RB_GSL_FFT_COPY);
174
+ }
175
+
176
+ static VALUE rb_gsl_fft_complex_radix2_backward2(VALUE obj)
177
+ {
178
+ return rb_fft_complex_radix2(obj, gsl_fft_complex_radix2_backward,
179
+ RB_GSL_FFT_INPLACE);
180
+ }
181
+
182
+ static VALUE rb_gsl_fft_complex_radix2_inverse2(VALUE obj)
183
+ {
184
+ return rb_fft_complex_radix2(obj, gsl_fft_complex_radix2_inverse,
185
+ RB_GSL_FFT_INPLACE);
186
+ }
187
+
188
+
189
+ static VALUE rb_gsl_fft_complex_radix2_dif_forward2(VALUE obj)
190
+ {
191
+ return rb_fft_complex_radix2(obj,
192
+ gsl_fft_complex_radix2_dif_forward,
193
+ RB_GSL_FFT_INPLACE);
194
+ }
195
+
196
+ static VALUE rb_gsl_fft_complex_radix2_dif_transform(VALUE obj, VALUE val_sign)
197
+ {
198
+ size_t stride, n;
199
+ gsl_complex_packed_array data;
200
+ gsl_vector_complex *vin, *vout;
201
+ gsl_fft_direction sign;
202
+ sign = NUM2INT(val_sign);
203
+ get_complex_stride_n(obj, &vin, &data, &stride, &n);
204
+ vout = gsl_vector_complex_alloc(n);
205
+ gsl_vector_complex_memcpy(vout, vin);
206
+ gsl_fft_complex_radix2_dif_transform(vout->data, vout->stride /*1*/, vout->size /*n*/, sign);
207
+ return Data_Wrap_Struct(cgsl_vector_complex, 0, gsl_vector_complex_free, vout);
208
+ }
209
+
210
+ /* in-place */
211
+ static VALUE rb_gsl_fft_complex_radix2_dif_transform2(VALUE obj, VALUE val_sign)
212
+ {
213
+ size_t stride, n;
214
+ gsl_complex_packed_array data;
215
+ gsl_fft_direction sign;
216
+ VALUE ary;
217
+ sign = NUM2INT(val_sign);
218
+ ary = get_complex_stride_n(obj, NULL, &data, &stride, &n);
219
+ gsl_fft_complex_radix2_dif_transform(data, stride, n, sign);
220
+ return ary;
221
+ }
222
+
223
+ static VALUE rb_gsl_fft_complex_radix2_dif_backward(VALUE obj)
224
+ {
225
+ return rb_fft_complex_radix2(obj,
226
+ gsl_fft_complex_radix2_dif_backward,
227
+ RB_GSL_FFT_COPY);
228
+ }
229
+ static VALUE rb_gsl_fft_complex_radix2_dif_inverse(VALUE obj)
230
+ {
231
+ return rb_fft_complex_radix2(obj,
232
+ gsl_fft_complex_radix2_dif_inverse,
233
+ RB_GSL_FFT_COPY);
234
+ }
235
+
236
+ static VALUE rb_gsl_fft_complex_radix2_dif_backward2(VALUE obj)
237
+ {
238
+ return rb_fft_complex_radix2(obj,
239
+ gsl_fft_complex_radix2_dif_backward,
240
+ RB_GSL_FFT_INPLACE);
241
+ }
242
+ static VALUE rb_gsl_fft_complex_radix2_dif_inverse2(VALUE obj)
243
+ {
244
+ return rb_fft_complex_radix2(obj,
245
+ gsl_fft_complex_radix2_dif_inverse,
246
+ RB_GSL_FFT_INPLACE);
247
+ }
248
+
249
+ static VALUE rb_GSL_FFT_Wavetable_n(VALUE obj)
250
+ {
251
+ GSL_FFT_Wavetable *table;
252
+ Data_Get_Struct(obj, GSL_FFT_Wavetable, table);
253
+ return INT2FIX(table->n);
254
+ }
255
+
256
+ static VALUE rb_GSL_FFT_Wavetable_nf(VALUE obj)
257
+ {
258
+ GSL_FFT_Wavetable *table;
259
+ Data_Get_Struct(obj, GSL_FFT_Wavetable, table);
260
+ return INT2FIX(table->nf);
261
+ }
262
+
263
+ static VALUE rb_GSL_FFT_Wavetable_factor(VALUE obj)
264
+ {
265
+ GSL_FFT_Wavetable *table;
266
+ gsl_vector_int *v;
267
+ size_t i;
268
+ Data_Get_Struct(obj, GSL_FFT_Wavetable, table);
269
+ v = gsl_vector_int_alloc(table->nf);
270
+ for (i = 0; i < table->nf; i++) gsl_vector_int_set(v, i, table->factor[i]);
271
+ return Data_Wrap_Struct(cgsl_vector_int, 0, gsl_vector_int_free, v);
272
+ }
273
+
274
+ enum {
275
+ NONE_OF_TWO = 0,
276
+ ALLOC_SPACE = 1,
277
+ ALLOC_TABLE = 2,
278
+ BOTH_OF_TWO = 3,
279
+ } FFTComplexStructAllocFlag;
280
+
281
+ static void gsl_fft_free(int flag, GSL_FFT_Wavetable *table,
282
+ GSL_FFT_Workspace *space);
283
+
284
+ // Parse argc, argv. obj must be GSL::Vector::Complex.
285
+ // This can be simplified at some point.
286
+ // See comments preceding get_complex_stride_n()
287
+ static int gsl_fft_get_argv_complex(int argc, VALUE *argv, VALUE obj,
288
+ gsl_vector_complex ** vin,
289
+ gsl_complex_packed_array *data, size_t *stride,
290
+ size_t *n, gsl_fft_complex_wavetable **table,
291
+ gsl_fft_complex_workspace **space)
292
+ {
293
+ int flag = NONE_OF_TWO, flagtmp, i, itmp = argc, itmp2 = 0, ccc;
294
+ int flagw = 0;
295
+
296
+ CHECK_VECTOR_COMPLEX(obj);
297
+
298
+ ccc = argc;
299
+ flagtmp = 0;
300
+ flagw = 0;
301
+ for (i = argc-1; i >= itmp2; i--) {
302
+ if (rb_obj_is_kind_of(argv[i], cgsl_fft_complex_workspace)) {
303
+ Data_Get_Struct(argv[i], gsl_fft_complex_workspace, *space);
304
+ flagtmp = 1;
305
+ flagw = 1;
306
+ itmp = i;
307
+ ccc--;
308
+ break;
309
+ }
310
+ }
311
+ flagtmp = 0;
312
+ for (i = itmp-1; i >= itmp2; i--) {
313
+ if (rb_obj_is_kind_of(argv[i], cgsl_fft_complex_wavetable)) {
314
+ Data_Get_Struct(argv[i], gsl_fft_complex_wavetable, *table);
315
+ flagtmp = 1;
316
+ ccc--;
317
+ break;
318
+ }
319
+ }
320
+ get_complex_stride_n(obj, vin, data, stride, n);
321
+ if (flagw == 0) {
322
+ *space = gsl_fft_complex_workspace_alloc(*n);
323
+ flag += ALLOC_SPACE;
324
+ }
325
+ if (flagtmp == 0) {
326
+ *table = gsl_fft_complex_wavetable_alloc(*n);
327
+ flag += ALLOC_TABLE;
328
+ }
329
+ if (*table == NULL) {
330
+ rb_raise(rb_eRuntimeError, "something wrong with wavetable");
331
+ }
332
+ if (*space == NULL) {
333
+ rb_raise(rb_eRuntimeError, "something wrong with workspace");
334
+ }
335
+ return flag;
336
+ }
337
+
338
+ // Parse argc, argv. obj must be GSL::Vector of real data
339
+ static int gsl_fft_get_argv_real(int argc, VALUE *argv, VALUE obj,
340
+ double **ptr, size_t *stride,
341
+ size_t *n, gsl_fft_real_wavetable **table,
342
+ gsl_fft_real_workspace **space, int *naflag)
343
+ {
344
+ int flag = NONE_OF_TWO, flagtmp, i, itmp = argc, itmp2 = 0, ccc;
345
+ int flagw = 0;
346
+ *naflag = 0;
347
+
348
+ *ptr = get_ptr_double3(obj, n, stride, naflag);
349
+
350
+ ccc = argc;
351
+ flagtmp = 0;
352
+ flagw = 0;
353
+ for (i = argc-1; i >= itmp2; i--) {
354
+ if (rb_obj_is_kind_of(argv[i], cgsl_fft_real_workspace)) {
355
+ Data_Get_Struct(argv[i], gsl_fft_real_workspace, *space);
356
+ flagtmp = 1;
357
+ flagw = 1;
358
+ itmp = i;
359
+ ccc--;
360
+ break;
361
+ }
362
+ }
363
+ flagtmp = 0;
364
+ for (i = itmp-1; i >= itmp2; i--) {
365
+ if (rb_obj_is_kind_of(argv[i], cgsl_fft_real_wavetable)) {
366
+ Data_Get_Struct(argv[i], gsl_fft_real_wavetable, *table);
367
+ flagtmp = 1;
368
+ ccc--;
369
+ break;
370
+ }
371
+ }
372
+ if (flagw == 0) {
373
+ *space = gsl_fft_real_workspace_alloc(*n);
374
+ flag += ALLOC_SPACE;
375
+ }
376
+ if (flagtmp == 0) {
377
+ *table = gsl_fft_real_wavetable_alloc(*n);
378
+ flag += ALLOC_TABLE;
379
+ }
380
+ if (*table == NULL) {
381
+ rb_raise(rb_eRuntimeError, "something wrong with wavetable");
382
+ }
383
+ if (*space == NULL) {
384
+ rb_raise(rb_eRuntimeError, "something wrong with workspace");
385
+ }
386
+ return flag;
387
+ }
388
+
389
+ // Parse argc, argv. obj must be GSL::Vector of halfcomplex data
390
+ static int gsl_fft_get_argv_halfcomplex(int argc, VALUE *argv, VALUE obj,
391
+ double **ptr, size_t *stride,
392
+ size_t *n, gsl_fft_halfcomplex_wavetable **table,
393
+ gsl_fft_real_workspace **space, int *naflag)
394
+ {
395
+ int flag = NONE_OF_TWO, flagtmp, i, itmp = argc, itmp2 = 0, ccc;
396
+ int flagw = 0;
397
+
398
+ *ptr = get_ptr_double3(obj, n, stride, naflag);
399
+
400
+ ccc = argc;
401
+ flagtmp = 0;
402
+ flagw = 0;
403
+ for (i = argc-1; i >= itmp2; i--) {
404
+ if (rb_obj_is_kind_of(argv[i], cgsl_fft_real_workspace)) {
405
+ Data_Get_Struct(argv[i], gsl_fft_real_workspace, *space);
406
+ flagtmp = 1;
407
+ flagw = 1;
408
+ itmp = i;
409
+ ccc--;
410
+ break;
411
+ }
412
+ }
413
+ flagtmp = 0;
414
+ for (i = itmp-1; i >= itmp2; i--) {
415
+ if (rb_obj_is_kind_of(argv[i], cgsl_fft_halfcomplex_wavetable)) {
416
+ Data_Get_Struct(argv[i], gsl_fft_halfcomplex_wavetable, *table);
417
+ flagtmp = 1;
418
+ ccc--;
419
+ break;
420
+ }
421
+ }
422
+ if (flagw == 0) {
423
+ *space = gsl_fft_real_workspace_alloc(*n);
424
+ flag += ALLOC_SPACE;
425
+ }
426
+ if (flagtmp == 0) {
427
+ *table = gsl_fft_halfcomplex_wavetable_alloc(*n);
428
+ flag += ALLOC_TABLE;
429
+ }
430
+ if (*table == NULL) {
431
+ rb_raise(rb_eRuntimeError, "something wrong with wavetable");
432
+ }
433
+ if (*space == NULL) {
434
+ rb_raise(rb_eRuntimeError, "something wrong with workspace");
435
+ }
436
+ return flag;
437
+ }
438
+
439
+ static void gsl_fft_free(int flag, GSL_FFT_Wavetable *table,
440
+ GSL_FFT_Workspace *space)
441
+ {
442
+ switch (flag) {
443
+ case ALLOC_TABLE:
444
+ GSL_FFT_Wavetable_free(table);
445
+ break;
446
+ case ALLOC_SPACE:
447
+ GSL_FFT_Workspace_free(space);
448
+ break;
449
+ case BOTH_OF_TWO:
450
+ GSL_FFT_Wavetable_free(table);
451
+ GSL_FFT_Workspace_free(space);
452
+ break;
453
+ default:
454
+ /* never happens */
455
+ break;
456
+ }
457
+ }
458
+
459
+ static VALUE rb_fft_complex_trans(int argc, VALUE *argv, VALUE obj,
460
+ int (*transform)(gsl_complex_packed_array,
461
+ size_t, size_t,
462
+ const gsl_fft_complex_wavetable *,
463
+ gsl_fft_complex_workspace *),
464
+ int sss)
465
+ {
466
+ int flag = 0, status;
467
+ size_t stride, n;
468
+ gsl_complex_packed_array data;
469
+ gsl_vector_complex *vin, *vout;
470
+ gsl_fft_complex_wavetable *table = NULL;
471
+ gsl_fft_complex_workspace *space = NULL;
472
+ flag = gsl_fft_get_argv_complex(argc, argv, obj, &vin, &data, &stride, &n, &table, &space);
473
+ if (sss == RB_GSL_FFT_COPY) {
474
+ vout = gsl_vector_complex_alloc(n);
475
+ gsl_vector_complex_memcpy(vout, vin);
476
+ status = (*transform)(vout->data, vout->stride /*1*/, vout->size /*n*/, table, space);
477
+ gsl_fft_free(flag, (GSL_FFT_Wavetable *) table, (GSL_FFT_Workspace *) space);
478
+ return Data_Wrap_Struct(cgsl_vector_complex, 0, gsl_vector_complex_free, vout);
479
+ } else { /* in-place */
480
+ status = (*transform)(data, stride, n, table, space);
481
+ gsl_fft_free(flag, (GSL_FFT_Wavetable *) table, (GSL_FFT_Workspace *) space);
482
+ return obj;
483
+ }
484
+ }
485
+
486
+ static VALUE rb_gsl_fft_complex_forward(int argc, VALUE *argv, VALUE obj)
487
+ {
488
+ return rb_fft_complex_trans(argc, argv, obj, gsl_fft_complex_forward,
489
+ RB_GSL_FFT_COPY);
490
+ }
491
+
492
+ static VALUE rb_gsl_fft_complex_forward2(int argc, VALUE *argv, VALUE obj)
493
+ {
494
+ return rb_fft_complex_trans(argc, argv, obj, gsl_fft_complex_forward,
495
+ RB_GSL_FFT_INPLACE);
496
+ }
497
+
498
+ static VALUE rb_gsl_fft_complex_transform(int argc, VALUE *argv, VALUE obj)
499
+ {
500
+ int flag = 0, status;
501
+ size_t stride, n;
502
+ gsl_vector_complex *vin, *vout;
503
+ gsl_fft_direction sign;
504
+ gsl_complex_packed_array data;
505
+ gsl_fft_complex_wavetable *table = NULL;
506
+ gsl_fft_complex_workspace *space = NULL;
507
+ CHECK_FIXNUM(argv[argc-1]);
508
+ sign = FIX2INT(argv[argc-1]);
509
+ flag = gsl_fft_get_argv_complex(argc-1, argv, obj, &vin, &data, &stride, &n, &table, &space);
510
+ vout = gsl_vector_complex_alloc(n);
511
+ gsl_vector_complex_memcpy(vout, vin);
512
+ status = gsl_fft_complex_transform(vout->data, stride, n, table, space, sign);
513
+ gsl_fft_free(flag, (GSL_FFT_Wavetable *) table, (GSL_FFT_Workspace *) space);
514
+ return Data_Wrap_Struct(cgsl_vector_complex, 0, gsl_vector_complex_free, vout);
515
+ }
516
+
517
+ /* in-place */
518
+ static VALUE rb_gsl_fft_complex_transform2(int argc, VALUE *argv, VALUE obj)
519
+ {
520
+ int flag = 0, status;
521
+ size_t stride, n;
522
+ gsl_fft_direction sign;
523
+ gsl_complex_packed_array data;
524
+ gsl_fft_complex_wavetable *table = NULL;
525
+ gsl_fft_complex_workspace *space = NULL;
526
+ CHECK_FIXNUM(argv[argc-1]);
527
+ sign = FIX2INT(argv[argc-1]);
528
+ flag = gsl_fft_get_argv_complex(argc-1, argv, obj, NULL, &data, &stride, &n, &table, &space);
529
+ status = gsl_fft_complex_transform(data, stride, n, table, space, sign);
530
+ gsl_fft_free(flag, (GSL_FFT_Wavetable *) table, (GSL_FFT_Workspace *) space);
531
+ return obj;
532
+ }
533
+
534
+ static VALUE rb_gsl_fft_complex_backward(int argc, VALUE *argv, VALUE obj)
535
+ {
536
+ return rb_fft_complex_trans(argc, argv, obj, gsl_fft_complex_backward,
537
+ RB_GSL_FFT_COPY);
538
+ }
539
+
540
+ static VALUE rb_gsl_fft_complex_backward2(int argc, VALUE *argv, VALUE obj)
541
+ {
542
+ return rb_fft_complex_trans(argc, argv, obj, gsl_fft_complex_backward,
543
+ RB_GSL_FFT_INPLACE);
544
+ }
545
+
546
+ static VALUE rb_gsl_fft_complex_inverse(int argc, VALUE *argv, VALUE obj)
547
+ {
548
+ return rb_fft_complex_trans(argc, argv, obj, gsl_fft_complex_inverse,
549
+ RB_GSL_FFT_COPY);
550
+ }
551
+
552
+ static VALUE rb_gsl_fft_complex_inverse2(int argc, VALUE *argv, VALUE obj)
553
+ {
554
+ return rb_fft_complex_trans(argc, argv, obj, gsl_fft_complex_inverse,
555
+ RB_GSL_FFT_INPLACE);
556
+ }
557
+
558
+ // The FFT methods used to allow passing stride and n values as optional
559
+ // parameters to control which elements get transformed. This created problems
560
+ // for Views which can have their own stride, so support for stride and n
561
+ // parameters to the transform methods is being dropped. This method used to
562
+ // be called to determine the stride and n values to use based on the
563
+ // parameters and/or the vector itself (depending on how many parameters were
564
+ // passed). Now this function is somewhat unneceesary, but to simplify the code
565
+ // refactoring, it has been left in place for the time being. Eventually it
566
+ // can be refactored away completely.
567
+ //
568
+ // obj must be GSL::Vector of real or halfcomplex data
569
+ static VALUE get_ptr_stride_n(VALUE obj,
570
+ double **ptr, size_t *stride, size_t *n, int *flag)
571
+ {
572
+ *flag = 0;
573
+ *ptr = get_ptr_double3(obj, n, stride, flag);
574
+ return obj;
575
+ }
576
+
577
+ static VALUE rb_fft_radix2(VALUE obj,
578
+ int (*trans)(double [], size_t, size_t),
579
+ int sss)
580
+ {
581
+ size_t stride, n;
582
+ gsl_vector *vnew;
583
+ gsl_vector_view vv;
584
+ double *ptr1, *ptr2;
585
+ int flag;
586
+ #ifdef HAVE_NARRAY_H
587
+ int shape[1];
588
+ #endif
589
+ VALUE ary;
590
+ get_ptr_stride_n(obj, &ptr1, &stride, &n, &flag);
591
+ if (flag == 0) {
592
+ if (sss == RB_GSL_FFT_COPY) {
593
+ vnew = gsl_vector_alloc(n);
594
+ vv.vector.data = ptr1;
595
+ vv.vector.stride = stride;
596
+ vv.vector.size = n;
597
+ gsl_vector_memcpy(vnew, &vv.vector);
598
+ ptr2 = vnew->data;
599
+ stride = 1;
600
+ ary = Data_Wrap_Struct(cgsl_vector, 0, gsl_vector_free, vnew);
601
+ } else {
602
+ ary = obj;
603
+ ptr2 = ptr1;
604
+ }
605
+ #ifdef HAVE_NARRAY_H
606
+ } else if (flag == 1) {
607
+ if (sss == RB_GSL_FFT_COPY) {
608
+ shape[0] = n;
609
+ ary = na_make_object(NA_DFLOAT, 1, shape, cNArray);
610
+ ptr2 = NA_PTR_TYPE(ary, double*);
611
+ memcpy(ptr2, ptr1, sizeof(double)*n);
612
+ stride = 1;
613
+ } else {
614
+ ary = obj;
615
+ ptr2 = NA_PTR_TYPE(ary, double*);
616
+ }
617
+ #endif
618
+ } else {
619
+ rb_raise(rb_eRuntimeError, "something wrong");
620
+ }
621
+ (*trans)(ptr2, stride, n);
622
+ return ary;
623
+ }
624
+
625
+ static VALUE rb_gsl_fft_real_radix2_transform(VALUE obj)
626
+ {
627
+ return rb_fft_radix2(obj, gsl_fft_real_radix2_transform,
628
+ RB_GSL_FFT_COPY);
629
+ }
630
+
631
+ static VALUE rb_gsl_fft_real_radix2_transform2(VALUE obj)
632
+ {
633
+ return rb_fft_radix2(obj, gsl_fft_real_radix2_transform,
634
+ RB_GSL_FFT_INPLACE);
635
+ }
636
+
637
+ static VALUE rb_gsl_fft_halfcomplex_radix2_inverse(VALUE obj)
638
+ {
639
+ return rb_fft_radix2(obj, gsl_fft_halfcomplex_radix2_inverse,
640
+ RB_GSL_FFT_COPY);
641
+ }
642
+
643
+ static VALUE rb_gsl_fft_halfcomplex_radix2_inverse2(VALUE obj)
644
+ {
645
+ return rb_fft_radix2(obj, gsl_fft_halfcomplex_radix2_inverse,
646
+ RB_GSL_FFT_INPLACE);
647
+ }
648
+
649
+ static VALUE rb_gsl_fft_halfcomplex_radix2_backward(VALUE obj)
650
+ {
651
+ return rb_fft_radix2(obj, gsl_fft_halfcomplex_radix2_backward,
652
+ RB_GSL_FFT_COPY);
653
+ }
654
+
655
+ static VALUE rb_gsl_fft_halfcomplex_radix2_backward2(VALUE obj)
656
+ {
657
+ return rb_fft_radix2(obj, gsl_fft_halfcomplex_radix2_backward,
658
+ RB_GSL_FFT_INPLACE);
659
+ }
660
+
661
+ /*****/
662
+
663
+ static VALUE rb_fft_real_trans(int argc, VALUE *argv, VALUE obj,
664
+ int (*trans)(double [], size_t, size_t,
665
+ const gsl_fft_real_wavetable *,
666
+ gsl_fft_real_workspace *),
667
+ int sss)
668
+ {
669
+ int flag = 0, status, naflag = 0;
670
+ size_t stride, n;
671
+ gsl_vector *vnew;
672
+ gsl_vector_view vv;
673
+ double *ptr1, *ptr2;
674
+ #ifdef HAVE_NARRAY_H
675
+ int shape[1];
676
+ #endif
677
+ gsl_fft_real_wavetable *table = NULL;
678
+ gsl_fft_real_workspace *space = NULL;
679
+ VALUE ary;
680
+ flag = gsl_fft_get_argv_real(argc, argv, obj, &ptr1, &stride, &n, &table, &space, &naflag);
681
+ if (naflag == 0) {
682
+ if (sss == RB_GSL_FFT_COPY) {
683
+ vnew = gsl_vector_alloc(n);
684
+ vv.vector.data = ptr1;
685
+ vv.vector.stride = stride;
686
+ vv.vector.size = n;
687
+ gsl_vector_memcpy(vnew, &vv.vector);
688
+ ptr2 = vnew->data;
689
+ stride = 1;
690
+ ary = Data_Wrap_Struct(cgsl_vector, 0, gsl_vector_free, vnew);
691
+ } else {
692
+ ptr2 = ptr1;
693
+ ary = obj;
694
+ }
695
+ #ifdef HAVE_NARRAY_H
696
+ } else if (naflag == 1) {
697
+ if (sss == RB_GSL_FFT_COPY) {
698
+ shape[0] = n;
699
+ ary = na_make_object(NA_DFLOAT, 1, shape, cNArray);
700
+ ptr2 = NA_PTR_TYPE(ary, double*);
701
+ memcpy(ptr2, ptr1, sizeof(double)*n);
702
+ stride = 1;
703
+ } else {
704
+ ptr2 = ptr1;
705
+ ary = obj;
706
+ }
707
+ #endif
708
+ } else {
709
+ rb_raise(rb_eRuntimeError, "something wrong");
710
+ }
711
+ status = (*trans)(ptr2, stride, n, table, space);
712
+ gsl_fft_free(flag, (GSL_FFT_Wavetable *) table, (GSL_FFT_Workspace *) space);
713
+ return ary;
714
+ }
715
+
716
+ static VALUE rb_gsl_fft_real_transform(int argc, VALUE *argv, VALUE obj)
717
+ {
718
+ return rb_fft_real_trans(argc, argv, obj, gsl_fft_real_transform,
719
+ RB_GSL_FFT_COPY);
720
+ }
721
+
722
+ static VALUE rb_gsl_fft_real_transform2(int argc, VALUE *argv, VALUE obj)
723
+ {
724
+ return rb_fft_real_trans(argc, argv, obj, gsl_fft_real_transform,
725
+ RB_GSL_FFT_INPLACE);
726
+ }
727
+
728
+ static VALUE rb_fft_halfcomplex_trans(int argc, VALUE *argv, VALUE obj,
729
+ int (*trans)(double [], size_t, size_t,
730
+ const gsl_fft_halfcomplex_wavetable *, gsl_fft_real_workspace *),
731
+ int sss)
732
+ {
733
+ int flag = 0, status, naflag = 0;
734
+ size_t stride, n;
735
+ gsl_vector *vnew;
736
+ gsl_vector_view vv;
737
+ double *ptr1, *ptr2;
738
+ #ifdef HAVE_NARRAY_H
739
+ int shape[1];
740
+ #endif
741
+ gsl_fft_halfcomplex_wavetable *table = NULL;
742
+ gsl_fft_real_workspace *space = NULL;
743
+ VALUE ary;
744
+ flag = gsl_fft_get_argv_halfcomplex(argc, argv, obj, &ptr1, &stride, &n,
745
+ &table, &space, &naflag);
746
+ if (naflag == 0) {
747
+ if (sss == RB_GSL_FFT_COPY) {
748
+ vnew = gsl_vector_alloc(n);
749
+ vv.vector.data = ptr1;
750
+ vv.vector.stride = stride;
751
+ vv.vector.size = n;
752
+ gsl_vector_memcpy(vnew, &vv.vector);
753
+ ptr2 = vnew->data;
754
+ stride = 1;
755
+ ary = Data_Wrap_Struct(cgsl_vector, 0, gsl_vector_free, vnew);
756
+ } else {
757
+ ptr2 = ptr1;
758
+ ary = obj;
759
+ }
760
+ #ifdef HAVE_NARRAY_H
761
+ } else if (naflag == 1) {
762
+ if (sss == RB_GSL_FFT_COPY) {
763
+ shape[0] = n;
764
+ ary = na_make_object(NA_DFLOAT, 1, shape, cNArray);
765
+ ptr2 = NA_PTR_TYPE(ary, double*);
766
+ memcpy(ptr2, ptr1, sizeof(double)*n);
767
+ stride = 1;
768
+ } else {
769
+ ptr2 = ptr1;
770
+ ary = obj;
771
+ }
772
+ #endif
773
+ } else {
774
+ rb_raise(rb_eRuntimeError, "something wrong");
775
+ }
776
+ status = (*trans)(ptr2, stride, n, table, space);
777
+ gsl_fft_free(flag, (GSL_FFT_Wavetable *) table, (GSL_FFT_Workspace *) space);
778
+ return ary;
779
+ }
780
+
781
+ static VALUE rb_gsl_fft_halfcomplex_transform(int argc, VALUE *argv, VALUE obj)
782
+ {
783
+ return rb_fft_halfcomplex_trans(argc, argv, obj,
784
+ gsl_fft_halfcomplex_transform,
785
+ RB_GSL_FFT_COPY);
786
+ }
787
+
788
+ static VALUE rb_gsl_fft_halfcomplex_transform2(int argc, VALUE *argv, VALUE obj)
789
+ {
790
+ return rb_fft_halfcomplex_trans(argc, argv, obj,
791
+ gsl_fft_halfcomplex_transform,
792
+ RB_GSL_FFT_INPLACE);
793
+ }
794
+
795
+ static VALUE rb_gsl_fft_halfcomplex_backward(int argc, VALUE *argv, VALUE obj)
796
+ {
797
+ return rb_fft_halfcomplex_trans(argc, argv, obj,
798
+ gsl_fft_halfcomplex_backward,
799
+ RB_GSL_FFT_COPY);
800
+ }
801
+
802
+ static VALUE rb_gsl_fft_halfcomplex_backward2(int argc, VALUE *argv, VALUE obj)
803
+ {
804
+ return rb_fft_halfcomplex_trans(argc, argv, obj,
805
+ gsl_fft_halfcomplex_backward,
806
+ RB_GSL_FFT_INPLACE);
807
+ }
808
+
809
+ static VALUE rb_gsl_fft_halfcomplex_inverse(int argc, VALUE *argv, VALUE obj)
810
+ {
811
+ return rb_fft_halfcomplex_trans(argc, argv, obj,
812
+ gsl_fft_halfcomplex_inverse,
813
+ RB_GSL_FFT_COPY);
814
+ }
815
+
816
+ static VALUE rb_gsl_fft_halfcomplex_inverse2(int argc, VALUE *argv, VALUE obj)
817
+ {
818
+ return rb_fft_halfcomplex_trans(argc, argv, obj,
819
+ gsl_fft_halfcomplex_inverse,
820
+ RB_GSL_FFT_INPLACE);
821
+ }
822
+
823
+ static VALUE rb_gsl_fft_real_unpack(VALUE obj)
824
+ {
825
+ gsl_vector *v;
826
+ gsl_vector_complex *vout;
827
+
828
+ CHECK_VECTOR(obj);
829
+ Data_Get_Struct(obj, gsl_vector, v);
830
+
831
+ vout = gsl_vector_complex_alloc(v->size);
832
+ gsl_fft_real_unpack(v->data, (gsl_complex_packed_array) vout->data, v->stride, v->size);
833
+ return Data_Wrap_Struct(cgsl_vector_complex, 0, gsl_vector_complex_free, vout);
834
+ }
835
+
836
+ static VALUE rb_gsl_fft_halfcomplex_unpack(VALUE obj)
837
+ {
838
+ gsl_vector *v;
839
+ gsl_vector_complex *vout;
840
+
841
+ CHECK_VECTOR(obj);
842
+ Data_Get_Struct(obj, gsl_vector, v);
843
+
844
+ vout = gsl_vector_complex_alloc(v->size);
845
+ gsl_fft_halfcomplex_unpack(v->data, (gsl_complex_packed_array) vout->data, v->stride, v->size);
846
+ return Data_Wrap_Struct(cgsl_vector_complex, 0, gsl_vector_complex_free, vout);
847
+ }
848
+
849
+ /* Convert a halfcomplex data to Numerical Recipes style */
850
+ static VALUE rb_gsl_fft_halfcomplex_to_nrc(VALUE obj)
851
+ {
852
+ gsl_vector *v, *vnew;
853
+ size_t i, k;
854
+
855
+ CHECK_VECTOR(obj);
856
+ Data_Get_Struct(obj, gsl_vector, v);
857
+
858
+ vnew = gsl_vector_alloc(v->size);
859
+ gsl_vector_set(vnew, 0, gsl_vector_get(v, 0)); /* DC */
860
+ gsl_vector_set(vnew, 1, gsl_vector_get(v, v->size/2)); /* Nyquist freq */
861
+ for (i = 2, k = 1; i < vnew->size; i+=2, k++) {
862
+ gsl_vector_set(vnew, i, gsl_vector_get(v, k));
863
+ gsl_vector_set(vnew, i+1, -gsl_vector_get(v, v->size-k));
864
+ }
865
+ return Data_Wrap_Struct(cgsl_vector, 0, gsl_vector_free, vnew);
866
+ }
867
+
868
+ static VALUE rb_gsl_fft_halfcomplex_amp_phase(VALUE obj)
869
+ {
870
+ gsl_vector *v;
871
+ gsl_vector *amp, *phase;
872
+ double re, im;
873
+ VALUE vamp, vphase;
874
+ size_t i;
875
+ CHECK_VECTOR(obj);
876
+ Data_Get_Struct(obj, gsl_vector, v);
877
+ amp = gsl_vector_alloc(v->size/2);
878
+ phase = gsl_vector_alloc(v->size/2);
879
+ gsl_vector_set(amp, 0, gsl_vector_get(v, 0));
880
+ gsl_vector_set(phase, 0, 0);
881
+ gsl_vector_set(amp, amp->size-1, gsl_vector_get(v, v->size-1));
882
+ gsl_vector_set(phase, phase->size-1, 0);
883
+ for (i = 1; i < v->size-1; i+=2) {
884
+ re = gsl_vector_get(v, i);
885
+ im = gsl_vector_get(v, i+1);
886
+ gsl_vector_set(amp, i/2+1, sqrt(re*re + im*im));
887
+ gsl_vector_set(phase, i/2+1, atan2(im, re));
888
+ }
889
+ vamp = Data_Wrap_Struct(VECTOR_ROW_COL(obj), 0, gsl_vector_free, amp);
890
+ vphase = Data_Wrap_Struct(VECTOR_ROW_COL(obj), 0, gsl_vector_free, phase);
891
+ return rb_ary_new3(2, vamp, vphase);
892
+ }
893
+
894
+ void Init_gsl_fft(VALUE module)
895
+ {
896
+ mgsl_fft = rb_define_module_under(module, "FFT");
897
+
898
+ /*****/
899
+
900
+ rb_define_const(mgsl_fft, "Forward", INT2FIX(forward));
901
+ rb_define_const(mgsl_fft, "FORWARD", INT2FIX(forward));
902
+ rb_define_const(mgsl_fft, "Backward", INT2FIX(backward));
903
+ rb_define_const(mgsl_fft, "BACKWARD", INT2FIX(backward));
904
+
905
+ /* Transforms for complex vectors */
906
+ rb_define_method(cgsl_vector_complex, "radix2_forward",
907
+ rb_gsl_fft_complex_radix2_forward, 0);
908
+ rb_define_method(cgsl_vector_complex, "radix2_transform",
909
+ rb_gsl_fft_complex_radix2_transform, 1);
910
+ rb_define_method(cgsl_vector_complex, "radix2_backward",
911
+ rb_gsl_fft_complex_radix2_backward, 0);
912
+ rb_define_method(cgsl_vector_complex, "radix2_inverse",
913
+ rb_gsl_fft_complex_radix2_inverse, 0);
914
+ rb_define_method(cgsl_vector_complex, "radix2_dif_forward",
915
+ rb_gsl_fft_complex_radix2_dif_forward, 0);
916
+ rb_define_method(cgsl_vector_complex, "radix2_dif_transform",
917
+ rb_gsl_fft_complex_radix2_dif_transform, 1);
918
+ rb_define_method(cgsl_vector_complex, "radix2_dif_backward",
919
+ rb_gsl_fft_complex_radix2_dif_backward, 0);
920
+ rb_define_method(cgsl_vector_complex, "radix2_dif_inverse",
921
+ rb_gsl_fft_complex_radix2_dif_inverse, 0);
922
+
923
+ /* In-place radix-2 transforms for complex vectors */
924
+ rb_define_method(cgsl_vector_complex, "radix2_forward!",
925
+ rb_gsl_fft_complex_radix2_forward2, 0);
926
+ rb_define_method(cgsl_vector_complex, "radix2_transform!",
927
+ rb_gsl_fft_complex_radix2_transform2, 1);
928
+ rb_define_method(cgsl_vector_complex, "radix2_backward!",
929
+ rb_gsl_fft_complex_radix2_backward2, 0);
930
+ rb_define_method(cgsl_vector_complex, "radix2_inverse!",
931
+ rb_gsl_fft_complex_radix2_inverse2, 0);
932
+ rb_define_method(cgsl_vector_complex, "radix2_dif_forward!",
933
+ rb_gsl_fft_complex_radix2_dif_forward2, 0);
934
+ rb_define_method(cgsl_vector_complex, "radix2_dif_transform!",
935
+ rb_gsl_fft_complex_radix2_dif_transform2, 1);
936
+ rb_define_method(cgsl_vector_complex, "radix2_dif_backward!",
937
+ rb_gsl_fft_complex_radix2_dif_backward2, 0);
938
+ rb_define_method(cgsl_vector_complex, "radix2_dif_inverse!",
939
+ rb_gsl_fft_complex_radix2_dif_inverse2, 0);
940
+
941
+ // class GSL::FFT::Wavetable < GSL::Object
942
+ //
943
+ // Useful since some functionality is shared among
944
+ // GSL::FFT::Complex::Wavetable
945
+ // GSL::FFT::Real::Wavetable
946
+ // GSL::FFT::HalfComplex::Wavetable
947
+ cgsl_fft_wavetable = rb_define_class_under(mgsl_fft, "Wavetable", cGSL_Object);
948
+ // No alloc
949
+ // TODO Make GSL::FFT::Wavetable#initialize private?
950
+ rb_define_method(cgsl_fft_wavetable, "n",
951
+ rb_GSL_FFT_Wavetable_n, 0);
952
+ rb_define_method(cgsl_fft_wavetable, "nf",
953
+ rb_GSL_FFT_Wavetable_nf, 0);
954
+ rb_define_method(cgsl_fft_wavetable, "factor",
955
+ rb_GSL_FFT_Wavetable_factor, 0);
956
+
957
+ // class GSL::FFT::ComplexWavetable < GSL::FFT::Wavetable
958
+ cgsl_fft_complex_wavetable = rb_define_class_under(mgsl_fft, "ComplexWavetable",
959
+ cgsl_fft_wavetable);
960
+ rb_define_singleton_method(cgsl_fft_complex_wavetable, "alloc",
961
+ rb_gsl_fft_complex_wavetable_new, 1);
962
+
963
+ // class GSL::FFT::ComplexWorkspace < GSL::Object
964
+ cgsl_fft_complex_workspace = rb_define_class_under(mgsl_fft, "ComplexWorkspace",
965
+ cGSL_Object);
966
+ rb_define_singleton_method(cgsl_fft_complex_workspace, "alloc",
967
+ rb_gsl_fft_complex_workspace_new, 1);
968
+
969
+ rb_define_method(cgsl_vector_complex, "forward", rb_gsl_fft_complex_forward, -1);
970
+ rb_define_method(cgsl_vector_complex, "transform", rb_gsl_fft_complex_transform, -1);
971
+ rb_define_method(cgsl_vector_complex, "backward", rb_gsl_fft_complex_backward, -1);
972
+ rb_define_method(cgsl_vector_complex, "inverse", rb_gsl_fft_complex_inverse, -1);
973
+
974
+ rb_define_method(cgsl_vector_complex, "forward!", rb_gsl_fft_complex_forward2, -1);
975
+ rb_define_method(cgsl_vector_complex, "transform!", rb_gsl_fft_complex_transform2, -1);
976
+ rb_define_method(cgsl_vector_complex, "backward!", rb_gsl_fft_complex_backward2, -1);
977
+ rb_define_method(cgsl_vector_complex, "inverse!", rb_gsl_fft_complex_inverse2, -1);
978
+
979
+ /*****/
980
+
981
+ // TODO Do these method names need the "real_" and "halfcomplex_" prefixes?
982
+ rb_define_method(cgsl_vector, "real_radix2_transform",
983
+ rb_gsl_fft_real_radix2_transform, 0);
984
+ rb_define_alias(cgsl_vector, "radix2_transform", "real_radix2_transform");
985
+ rb_define_alias(cgsl_vector, "radix2_forward", "real_radix2_transform");
986
+ rb_define_method(cgsl_vector, "real_radix2_inverse",
987
+ rb_gsl_fft_halfcomplex_radix2_inverse, 0);
988
+ rb_define_alias(cgsl_vector, "radix2_inverse", "real_radix2_inverse");
989
+ rb_define_alias(cgsl_vector, "halfcomplex_radix2_inverse",
990
+ "real_radix2_inverse");
991
+ rb_define_method(cgsl_vector, "real_radix2_backward",
992
+ rb_gsl_fft_halfcomplex_radix2_backward, 0);
993
+ rb_define_alias(cgsl_vector, "radix2_backward", "real_radix2_backward");
994
+ rb_define_alias(cgsl_vector, "halfcomplex_radix2_backward",
995
+ "real_radix2_backward");
996
+
997
+ // TODO Do these method names need the "real_" and "halfcomplex_" prefixes?
998
+ rb_define_method(cgsl_vector, "real_radix2_transform!",
999
+ rb_gsl_fft_real_radix2_transform2, 0);
1000
+ rb_define_alias(cgsl_vector, "radix2_transform!", "real_radix2_transform!");
1001
+ rb_define_alias(cgsl_vector, "radix2_forward!", "real_radix2_transform!");
1002
+ rb_define_method(cgsl_vector, "real_radix2_inverse!",
1003
+ rb_gsl_fft_halfcomplex_radix2_inverse2, 0);
1004
+ rb_define_alias(cgsl_vector, "radix2_inverse!", "real_radix2_inverse!");
1005
+ rb_define_alias(cgsl_vector, "halfcomplex_radix2_inverse!",
1006
+ "real_radix2_inverse!");
1007
+ rb_define_method(cgsl_vector, "real_radix2_backward!",
1008
+ rb_gsl_fft_halfcomplex_radix2_backward2, 0);
1009
+ rb_define_alias(cgsl_vector, "radix2_backward!", "real_radix2_backward!");
1010
+ rb_define_alias(cgsl_vector, "halfcomplex_radix2_backward!",
1011
+ "real_radix2_backward!");
1012
+
1013
+ /*****/
1014
+
1015
+ // class GSL::FFT::RealWavetable < GSL::FFT::Wavetable
1016
+ cgsl_fft_real_wavetable = rb_define_class_under(mgsl_fft, "RealWavetable",
1017
+ cgsl_fft_wavetable);
1018
+ rb_define_singleton_method(cgsl_fft_real_wavetable, "alloc",
1019
+ rb_gsl_fft_real_wavetable_new, 1);
1020
+
1021
+ // class GSL::FFT::HalfComplexWavetable < GSL::FFT::Wavetable
1022
+ cgsl_fft_halfcomplex_wavetable = rb_define_class_under(mgsl_fft,
1023
+ "HalfComplexWavetable", cgsl_fft_wavetable);
1024
+ rb_define_singleton_method(cgsl_fft_halfcomplex_wavetable, "alloc",
1025
+ rb_gsl_fft_halfcomplex_wavetable_new, 1);
1026
+
1027
+ /*****/
1028
+
1029
+ // class GSL::FFT::RealWorkspace < GSL::Object
1030
+ cgsl_fft_real_workspace = rb_define_class_under(mgsl_fft, "RealWorkspace",
1031
+ cGSL_Object);
1032
+ rb_define_singleton_method(cgsl_fft_real_workspace, "alloc",
1033
+ rb_gsl_fft_real_workspace_new, 1);
1034
+
1035
+ /*****/
1036
+
1037
+ // TODO Do these method names need the "real_" and "halfcomplex_" prefixes?
1038
+ rb_define_method(cgsl_vector, "real_transform", rb_gsl_fft_real_transform, -1);
1039
+ rb_define_alias(cgsl_vector, "transform", "real_transform");
1040
+ rb_define_alias(cgsl_vector, "forward", "real_transform");
1041
+ rb_define_alias(cgsl_vector, "fft_forward", "real_transform");
1042
+ rb_define_alias(cgsl_vector, "fft", "real_transform");
1043
+ rb_define_method(cgsl_vector, "halfcomplex_transform",
1044
+ rb_gsl_fft_halfcomplex_transform, -1);
1045
+ rb_define_method(cgsl_vector, "halfcomplex_backward",
1046
+ rb_gsl_fft_halfcomplex_backward, -1);
1047
+ rb_define_alias(cgsl_vector, "backward", "halfcomplex_backward");
1048
+ rb_define_alias(cgsl_vector, "fft_backward", "halfcomplex_backward");
1049
+ rb_define_method(cgsl_vector, "halfcomplex_inverse",
1050
+ rb_gsl_fft_halfcomplex_inverse, -1);
1051
+ rb_define_alias(cgsl_vector, "fft_inverse", "halfcomplex_inverse");
1052
+ rb_define_alias(cgsl_vector, "ifft", "halfcomplex_inverse");
1053
+ rb_define_alias(cgsl_vector, "inverse", "halfcomplex_inverse");
1054
+
1055
+ rb_define_method(cgsl_vector, "real_transform!", rb_gsl_fft_real_transform2, -1);
1056
+ rb_define_alias(cgsl_vector, "transform!", "real_transform!");
1057
+ rb_define_alias(cgsl_vector, "forward!", "real_transform!");
1058
+ rb_define_alias(cgsl_vector, "fft_forward!", "real_transform!");
1059
+ rb_define_alias(cgsl_vector, "fft!", "real_transform!");
1060
+ rb_define_method(cgsl_vector, "halfcomplex_transform!",
1061
+ rb_gsl_fft_halfcomplex_transform2, -1);
1062
+ rb_define_method(cgsl_vector, "halfcomplex_backward!",
1063
+ rb_gsl_fft_halfcomplex_backward2, -1);
1064
+ rb_define_alias(cgsl_vector, "backward!", "halfcomplex_backward!");
1065
+ rb_define_alias(cgsl_vector, "fft_backward!", "halfcomplex_backward!");
1066
+ rb_define_method(cgsl_vector, "halfcomplex_inverse!",
1067
+ rb_gsl_fft_halfcomplex_inverse2, -1);
1068
+ rb_define_alias(cgsl_vector, "fft_inverse!", "halfcomplex_inverse!");
1069
+ rb_define_alias(cgsl_vector, "ifft!", "halfcomplex_inverse!");
1070
+ rb_define_alias(cgsl_vector, "inverse!", "halfcomplex_inverse!");
1071
+
1072
+ /***/
1073
+ rb_define_method(cgsl_vector, "fft_real_unpack", rb_gsl_fft_real_unpack, 0);
1074
+ rb_define_alias(cgsl_vector, "real_unpack", "fft_real_unpack");
1075
+ rb_define_alias(cgsl_vector, "real_to_complex", "fft_real_unpack");
1076
+ rb_define_alias(cgsl_vector, "r_to_c", "fft_real_unpack");
1077
+
1078
+ rb_define_method(cgsl_vector, "fft_halfcomplex_unpack",
1079
+ rb_gsl_fft_halfcomplex_unpack, 0);
1080
+ rb_define_alias(cgsl_vector, "halfcomplex_unpack", "fft_halfcomplex_unpack");
1081
+ rb_define_alias(cgsl_vector, "halfcomplex_to_complex", "fft_halfcomplex_unpack");
1082
+ rb_define_alias(cgsl_vector, "hc_to_c", "fft_halfcomplex_unpack");
1083
+
1084
+ /*****/
1085
+
1086
+ rb_define_method(cgsl_vector, "to_nrc_order",
1087
+ rb_gsl_fft_halfcomplex_to_nrc, 0);
1088
+
1089
+ rb_define_method(cgsl_vector, "halfcomplex_amp_phase",
1090
+ rb_gsl_fft_halfcomplex_amp_phase, 0);
1091
+ rb_define_alias(cgsl_vector, "hc_amp_phase", "halfcomplex_amp_phase");
1092
+ }