pspline 5.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +5 -0
  3. data/README.md +34 -0
  4. data/Rakefile +6 -0
  5. data/bin/console +14 -0
  6. data/bin/setup +8 -0
  7. data/ext/pspline/basis.cpp +351 -0
  8. data/ext/pspline/example/exbspline.ps +2194 -0
  9. data/ext/pspline/example/exbspline.rb +36 -0
  10. data/ext/pspline/example/excspline.ps +2985 -0
  11. data/ext/pspline/example/excspline.rb +36 -0
  12. data/ext/pspline/example/exdspline.ps +2846 -0
  13. data/ext/pspline/example/exdspline.rb +33 -0
  14. data/ext/pspline/example/exfspline.rb +66 -0
  15. data/ext/pspline/example/exfspline1.rb +40 -0
  16. data/ext/pspline/example/expspline.ps +3299 -0
  17. data/ext/pspline/example/expspline.rb +29 -0
  18. data/ext/pspline/example/expspline1.rb +29 -0
  19. data/ext/pspline/example/expspline2.rb +47 -0
  20. data/ext/pspline/example/exqspline.ps +2957 -0
  21. data/ext/pspline/example/exqspline.rb +31 -0
  22. data/ext/pspline/example/exqspline1.rb +31 -0
  23. data/ext/pspline/example/exqspline2.rb +50 -0
  24. data/ext/pspline/example/exqspline3.rb +51 -0
  25. data/ext/pspline/example/exrspline.ps +2812 -0
  26. data/ext/pspline/example/exrspline.rb +34 -0
  27. data/ext/pspline/example/exrspline1.rb +34 -0
  28. data/ext/pspline/example/exrspline2.rb +44 -0
  29. data/ext/pspline/example/exsspline.ps +1965 -0
  30. data/ext/pspline/example/exsspline.rb +35 -0
  31. data/ext/pspline/example/exsspline1.rb +35 -0
  32. data/ext/pspline/example/extspline.ps +2767 -0
  33. data/ext/pspline/example/extspline.rb +32 -0
  34. data/ext/pspline/extconf.rb +7 -0
  35. data/ext/pspline/fft.cpp +552 -0
  36. data/ext/pspline/include/basis/basis.h +137 -0
  37. data/ext/pspline/include/basis/fft.h +152 -0
  38. data/ext/pspline/include/basis/poly_array.h +1568 -0
  39. data/ext/pspline/include/basis/pspline.h +506 -0
  40. data/ext/pspline/include/basis/uspline.h +210 -0
  41. data/ext/pspline/include/basis/util.h +656 -0
  42. data/ext/pspline/include/bspline.h +377 -0
  43. data/ext/pspline/include/bspline_Config.h +2 -0
  44. data/ext/pspline/plotsub.cpp +132 -0
  45. data/ext/pspline/pspline.cpp +897 -0
  46. data/ext/pspline/util.cpp +483 -0
  47. data/lib/pspline.rb +6 -0
  48. data/lib/pspline/version.rb +3 -0
  49. data/pspline.gemspec +25 -0
  50. metadata +122 -0
@@ -0,0 +1,32 @@
1
+ #! /usr/local/bin/ruby
2
+ require 'pspline'
3
+ include PSPLINE
4
+
5
+ #
6
+ #puts "# Interpolation of the Jacobi function"
7
+ #
8
+ XY = [ [ 0.0, 0.0 ],[ 0.5474, 0.5 ],[ 1.2837, 0.86603],[ 2.7681, 1.0 ],
9
+ [ 4.2525, 0.86603],[ 4.9888, 0.5 ],[ 5.5362, 0.0 ],[ 6.0836,-0.5 ],
10
+ [ 6.8199,-0.86603],[ 8.3043,-1.0 ],[ 9.7887,-0.86603],[10.5250,-0.5 ],
11
+ [11.0724, 0.0 ] ]
12
+
13
+ Jbn = ARGV[0].to_i
14
+
15
+ Dp = 10
16
+
17
+ Bs = Bspline.new(XY, 12, 5, 1)
18
+
19
+ vv = []
20
+ XY.each do |p|
21
+ printf "%7.4f, % f\n", p[0], p[1]
22
+ vv.push p[0]
23
+ end
24
+ printf "# value of interpolation points, Dp = %d", Dp
25
+ if Jbn == 0
26
+ print "\n"
27
+ else
28
+ printf ", Jbn = %d\n", Jbn
29
+ end
30
+ s = Bs.plot(vv, 10, Jbn) do |u, v|
31
+ printf "%8.5f % f\n", u, v[0]
32
+ end
@@ -0,0 +1,7 @@
1
+ require 'mkmf'
2
+
3
+ dir_config('PSPLINE','.')
4
+ $CPPFLAGS += " -std=c++11"
5
+ if have_header('bspline.h')
6
+ create_makefile('pspline')
7
+ end
@@ -0,0 +1,552 @@
1
+ #include <stddef.h>
2
+ #include <stdlib.h>
3
+ #include <stdio.h>
4
+ #include <string.h>
5
+ #include <math.h>
6
+ #include <assert.h>
7
+ #include "bspline.h"
8
+
9
+ #ifndef M_PI
10
+ #define M_PI 3.14159265358979323846
11
+ #endif
12
+
13
+
14
+ #define SDIM 10
15
+
16
+ template <typename T>
17
+ inline void relat(T & xr, T & xi, T wqr, T wqi)
18
+ {
19
+ T wtemp = xr;
20
+ xr = wtemp * wqr - xi * wqi;
21
+ xi = wtemp * wqi + xi * wqr;
22
+ }
23
+ template <typename T>
24
+ inline void relat(T & yr, T & yi, T xr, T xi, T gr, T gi)
25
+ {
26
+ T wtemp = yr;
27
+ yr = wtemp * xr - yi * xi + gr;
28
+ yi = wtemp * xi + yi * xr + gi;
29
+ }
30
+ template <typename T>
31
+ inline void relat(T *xr, T *xi, T *yr, T *yi, T wr, T wi)
32
+ {
33
+ T tr = wr * (*yr) - wi * (*yi);
34
+ T ti = wr * (*yi) + wi * (*yr);
35
+ *yr = *xr - tr; *xr += tr;
36
+ *yi = *xi - ti; *xi += ti;
37
+ }
38
+ /*******************************************************************************
39
+ 複素高速フーリエ変換(実数配列の引数)
40
+ Fast Fourier Transformation / Cooley-Tukey Method
41
+ *******************************************************************************/
42
+ template <typename T>
43
+ void cft2(T *data, size_t n, int f)
44
+ {
45
+ size_t mmax, m, j, istep, i, N = n >> 1;
46
+ T wr, wi, wpr, wpi, theta;
47
+
48
+ // ビット反転アルゴリズム
49
+ for (j = 1, i = 1; i < n; i += 2) {
50
+ if (j > i) { // 複素数を交換
51
+ wr = data[j-1]; data[j-1] = data[i-1]; data[i-1] = wr;
52
+ wi = data[ j ]; data[ j ] = data[ i ]; data[ i ] = wi;
53
+ }
54
+ m = N;
55
+ while(m >= 2 && j > m) { j -= m; m >>= 1; }
56
+ j += m;
57
+ }
58
+ T F = -f;
59
+ mmax = 2; theta = M_PI * F;
60
+ while (n > mmax) {
61
+ istep = mmax << 1;
62
+ wpr = cos(theta); wpi = sin(theta); // 三角関数の漸化式の初期値
63
+ wr = 1.0; wi = 0.0;
64
+ for (m = 1; m < mmax; m += 2) { // 2重の内側ループ
65
+ for (i = m; i <= n; i += istep) {
66
+ j = i + mmax;
67
+ relat<T>(&data[i-1], &data[i], &data[j-1], &data[j], wr, wi);
68
+ }
69
+ relat<T>(wr, wi, wpr, wpi); // 三角関数の漸化式
70
+ }
71
+ mmax = istep;
72
+ theta /= 2.0;
73
+ }
74
+ }
75
+ /*
76
+ 任意基数のFFT
77
+ */
78
+ template <typename T, size_t R>
79
+ void cft(T *data, size_t n, int f)
80
+ {
81
+ size_t h, i, j, k, L, m, mmax, istep;
82
+ size_t N = n >> 1, Nr = N / R;
83
+ T wr, wi, wpr, wpi, wqr, wqi, Xr, Xi, Yr, Yi, *gw;
84
+ gw = new T[R*2];
85
+ // R進数の桁反転
86
+ for (j = 1, i = 1; i < n; i += 2) {
87
+ if (i < j) {
88
+ wr = data[i-1]; data[i-1] = data[j-1]; data[j-1] = wr;
89
+ wi = data[ i ]; data[ i ] = data[ j ]; data[ j ] = wi;
90
+ }
91
+ m = (R-1) * (Nr << 1);
92
+ while (m >= 2 && j > m) {j -= m; m /= R;}
93
+ j += m / (R-1);
94
+ }
95
+ T F = -f;
96
+ T theta = 2 * M_PI * F / (T)R;
97
+ wqr = cos(theta); wqi = sin(theta);
98
+ mmax = 2;
99
+ while (n > mmax) {
100
+ istep = mmax * R;
101
+ wpr = cos(theta); wpi = sin(theta);
102
+ wr = 1.0; wi = 0.0;
103
+ for (m = 1; m < mmax; m += 2) {
104
+ for (i = m; i <= n; i += istep) {
105
+ for (j = i, L = 0; L < R; L++, j += mmax) {
106
+ h = (L << 1) + 1;
107
+ gw[h-1] = data[j-1]; gw[h] = data[j];
108
+ }
109
+ // バタフライ演算
110
+ Xr = wr; Xi = wi;
111
+ for (j = i, L = 0; L < R; L++, j += mmax) {
112
+ Yr = Yi = 0;
113
+ for (k = R; k > 0; --k) {
114
+ h = (k << 1) - 1;
115
+ relat<T>(Yr, Yi, Xr, Xi, gw[h-1], gw[h]);
116
+ } data[j-1] = Yr; data[j] = Yi;
117
+ relat<T>(Xr, Xi, wqr, wqi);
118
+ }
119
+ }
120
+ relat<T>(wr, wi, wpr, wpi);
121
+ }
122
+ mmax = istep;
123
+ theta /= R;
124
+ }
125
+ delete[] gw;
126
+ }
127
+ /*
128
+ 複数基数のFFT subroutine
129
+ */
130
+ template <typename T>
131
+ void cft(size_t r, T *data, size_t n, int f, size_t stride = 1)
132
+ {
133
+ size_t h, i, j, k, L, Li, Lj;
134
+ T xr, xi, yr, yi, *gw;
135
+ size_t N = n >> 1, Nr = N / r; // N = r**M;
136
+ gw = new T[r*2];
137
+ // r進数の桁反転
138
+ for (j = Nr, i = 1; i < N - 1; ++i) {
139
+ if (i < j) {
140
+ size_t ki = (i * stride) << 1;
141
+ size_t kj = (j * stride) << 1;
142
+ xr = data[ ki ]; data[ ki ] = data[ kj ]; data[ kj ] = xr;
143
+ xi = data[ki+1]; data[ki+1] = data[kj+1]; data[kj+1] = xi;
144
+ }
145
+ size_t m = (r-1) * Nr;
146
+ while (m > 0 && j >= m) {j -= m; m /= r;}
147
+ j += m / (r-1);
148
+ }
149
+ T F = -f;
150
+ T theta = 2 * M_PI * F / r;
151
+ T wqr = cos(theta), wqi = sin(theta);
152
+ size_t Nj = 1;
153
+ while (Nj < N) {
154
+ size_t step = Nj * r;
155
+ T wpr = cos(theta), wpi = sin(theta);
156
+ T wr = 1.0, wi = 0.0;
157
+ for (L = 0; L < Nj; ++L) {
158
+ for (h = L; h < N; h += step) {
159
+ size_t m = h * stride;
160
+ for (Li = m, Lj = 0; Lj < r; ++Lj, Li += Nj * stride) {
161
+ i = Li << 1; j = Lj << 1;
162
+ gw[j] = data[i]; gw[j+1] = data[i+1];
163
+ }
164
+ // バタフライ演算
165
+ xr = wr; xi = wi;
166
+ for (Li = m, Lj = 0; Lj < r; Lj++, Li += Nj * stride) {
167
+ yr = yi = 0;
168
+ for (k = r; k > 0; --k) {
169
+ j = (k << 1) - 1;
170
+ relat<T>(yr, yi, xr, xi, gw[j-1], gw[j]);
171
+ } i = Li << 1;
172
+ data[i] = yr; data[i+1] = yi;
173
+ relat<T>(xr, xi, wqr, wqi);
174
+ }
175
+ }
176
+ relat<T>(wr, wi, wpr, wpi);
177
+ }
178
+ theta /= r;
179
+ Nj = step;
180
+ }
181
+ delete[] gw;
182
+ }
183
+ /*
184
+ 複数基数のFFT main routine
185
+ g : データ配列
186
+ N : データ個数
187
+ f : 1 forward, 0 backword, -1 invert
188
+ */
189
+ template <typename T>
190
+ bool cft(T *data, size_t n, int f)
191
+ {
192
+ size_t N = n >> 1, Nres = N, s = 0, k;
193
+ size_t Ni[SDIM], ni[SDIM], M[SDIM], r[SDIM] = {2};
194
+ // Chinese Remainder Theorem
195
+ do {
196
+ M[s] = 0; ni[s] = 1; Ni[s] = N;
197
+ while (Ni[s] % r[s] == 0) {
198
+ M[s]++;
199
+ ni[s] *= r[s]; // ni = r**M;
200
+ Ni[s] /= r[s];
201
+ } Nres /= ni[s];
202
+ int rnew;
203
+ if (Nres != 1) {
204
+ rnew = r[s] + (r[s] == 2 ? 1 : 2);
205
+ if (M[s] > 0) s++;
206
+ if (s < SDIM) {
207
+ // 素因数分解
208
+ while (Nres % rnew != 0) rnew += 2;
209
+ r[s] = rnew;
210
+ }
211
+ }
212
+ } while (Nres > 1 && s < SDIM);
213
+ int F = (f > 0) ? 1 : -1;
214
+ if (s >= SDIM) return false; else
215
+ if (s == 0) {
216
+ switch (r[s]) {
217
+ case 2: cft2<T>(data, n, F); break;
218
+ case 3: cft<T,3>(data, n, F); break;
219
+ case 5: cft<T,5>(data, n, F); break;
220
+ case 7: cft<T,7>(data, n, F); break;
221
+ default: cft<T>(r[s], data, n, F);
222
+ }
223
+ } else {
224
+ size_t smax = s + 1;
225
+ T gw[n];
226
+ // 最初の並び替え
227
+ for (k = 0; k < N; ++k) {
228
+ size_t ks, kk = 0;
229
+ for (s = 0; s < smax; ++s)
230
+ kk = kk * ni[s] + k % ni[s];
231
+ kk <<= 1; ks = k << 1;
232
+ gw[kk] = data[ks]; gw[kk+1] = data[ks+1];
233
+ }
234
+ size_t step, stride = 1;
235
+ // フーリエ変換
236
+ for (k = smax; k > 0; --k) {
237
+ s = k - 1;
238
+ step = stride * ni[s];
239
+ for (size_t k1 = 0; k1 < stride; ++k1)
240
+ for (size_t k0 = k1; k0 < N; k0 += step)
241
+ cft(r[s], &gw[k0<<1], ni[s] << 1, F, stride);
242
+ stride = step;
243
+ }
244
+ // 最終の並び替え
245
+ for (k = 0; k < N; ++k) {
246
+ size_t Ls, Lu, L = 0, LL = 0;
247
+ for (s = 0; s < smax; ++s) {
248
+ Ls = k % ni[s];
249
+ LL = LL * ni[s] + Ls;
250
+ L += Ni[s] * Ls;
251
+ } Ls = (L % N) << 1;
252
+ Lu = LL << 1;
253
+ data[Ls] = gw[Lu]; data[Ls+1] = gw[Lu+1];
254
+ }
255
+ }
256
+ if (f < 0) for (k = 0; k < n; ++k) data[k] /= N;
257
+ return true;
258
+ }
259
+ /*******************************************************************************
260
+ 実数値高速フーリエ変換
261
+ Fast Fourier Transformation / Cooley-Tukey Method
262
+ *******************************************************************************/
263
+ /*
264
+ 基数2のFFT
265
+ */
266
+ template <typename T>
267
+ void rft2(T *data, size_t N, int f)
268
+ {
269
+ size_t i, j, NH = N >> 1;
270
+ T c, g1r, g1i, g2r, g2i, temp;
271
+ T wr, wi, wpr, wpi, wtemp;
272
+ T F = -f, theta = M_PI * F / (T)NH;
273
+
274
+ wpr = cos(theta); wpi = sin(theta);
275
+ if (f < 0) {
276
+ wr = data[0]; wi = data[N-1];
277
+ data[0] = wr + wi; wtemp = wr - wi;
278
+ wr = 0.0; wi = 1.0;
279
+ for (i = 2; i <= NH; i += 2) {
280
+ relat<T>(wr, wi, wpr, wpi);
281
+ j = N - i; temp = data[i-1]; data[i-1] = wtemp;
282
+ g1r = (temp + data[j-1]); g1i = (data[i] - data[j]);
283
+ g2r = (temp - data[j-1]); g2i = (data[i] + data[j]);
284
+ relat<T>(g2r, g2i, wr, wi);
285
+ if (i < j) {
286
+ data[i] = g1r + g2r; wtemp = g1i + g2i;
287
+ }
288
+ data[j] = g1r - g2r; data[j+1] = g2i - g1i;
289
+ }
290
+ }
291
+ cft2(data, N, f);
292
+ if (f > 0) {
293
+ c = 0.5;
294
+ wr = data[0]; wi = data[1];
295
+ data[0] = wr + wi; wtemp = wr - wi;
296
+ wr = 0.0; wi = -1.0;
297
+ for (i = 2; i <= NH; i += 2) {
298
+ relat<T>(wr, wi, wpr, wpi);
299
+ j = N - i; temp = data[j+1]; data[j+1] = wtemp;
300
+ g1r = c*(data[i] + data[j]); g1i = c*(data[i+1] - temp);
301
+ g2r = c*(data[i] - data[j]); g2i = c*(data[i+1] + temp);
302
+ relat<T>(g2r, g2i, wr, wi);
303
+ data[i-1] = g1r + g2r; data[i] = g1i + g2i;
304
+ if (i < j) {
305
+ wtemp = g1r - g2r; data[j] = g2i - g1i;
306
+ }
307
+ }
308
+ }
309
+ }
310
+ /*
311
+ 任意基数のFFT
312
+ */
313
+ template <typename T, size_t R>
314
+ void rft(T *data, size_t N, int f)
315
+ {
316
+ size_t h, i, j, k, L, m, mmax, istep;
317
+ size_t n = N << 1, Nr = N / R;
318
+ T wr, wi, wpr, wpi, wqr, wqi, *temp;
319
+ T xr, xi, yr, yi, *gw;
320
+ temp = new T[n]; gw = new T[R*2];
321
+ // R進数の桁反転
322
+ for (j = 1, i = 0; i < n; i += 2) {
323
+ if (f > 0) {
324
+ xr = data[i>>1];
325
+ xi = 0;
326
+ } else if (i == 0) {
327
+ xr = data[0];
328
+ xi = 0;
329
+ } else if (i < n/2) {
330
+ xr = data[i-1];
331
+ xi = data[ i ];
332
+ } else if (i == n/2) {
333
+ xr = data[i-1];
334
+ xi = 0;
335
+ } else {
336
+ xr = data[n-i-1];
337
+ xi =-data[ n-i ];
338
+ }
339
+ temp[j-1] = xr; temp[j] = xi;
340
+ m = (R-1) * (Nr << 1);
341
+ while (m >= 2 && j > m) {j -= m; m /= R;}
342
+ j += m / (R-1);
343
+ }
344
+ T F = -f;
345
+ T theta = 2.0 * M_PI * F / (T)R;
346
+ wqr = cos(theta); wqi = sin(theta);
347
+ mmax = 2;
348
+ while (n > mmax) {
349
+ istep = mmax * R;
350
+ wpr = cos(theta); wpi = sin(theta);
351
+ wr = 1.0; wi = 0.0;
352
+ for (m = 1; m < mmax; m += 2) {
353
+ for (i = m; i <= n; i += istep) {
354
+ for (j = i, L = 0; L < R; L++, j += mmax) {
355
+ h = (L << 1) + 1;
356
+ gw[h-1] = temp[j-1]; gw[h] = temp[j];
357
+ }
358
+ // バタフライ演算
359
+ xr = wr; xi = wi;
360
+ for (j = i, L = 0; L < R; L++, j += mmax) {
361
+ yr = yi = 0;
362
+ for (k = R; k > 0; --k) {
363
+ h = (k << 1) - 1;
364
+ relat<T>(yr, yi, xr, xi, gw[h-1], gw[h]);
365
+ } temp[j-1] = yr; temp[j] = yi;
366
+ relat<T>(xr, xi, wqr, wqi);
367
+ }
368
+ }
369
+ relat<T>(wr, wi, wpr, wpi);
370
+ }
371
+ mmax = istep;
372
+ theta /= R;
373
+ }
374
+ data[0] = temp[0];
375
+ for (i = 1; i < N; ++i) data[i] = temp[f > 0 ? i + 1 : i << 1];
376
+ delete[] gw; delete[] temp;
377
+ }
378
+ /*
379
+ 複数基数のFFT subroutine
380
+ */
381
+ template <typename T>
382
+ void rft(size_t r, T *data, size_t N, int f)
383
+ {
384
+ size_t h, i, j, k, L, m, mmax, istep;
385
+ size_t n = N << 1, Nr = N / r;
386
+ T wr, wi, wpr, wpi, wqr, wqi, *temp;
387
+ T xr, xi, yr, yi, *gw;
388
+ temp = new T[n]; gw = new T[r*2];
389
+ // r進数の桁反転
390
+ for (j = 1, i = 0; i < n; i += 2) {
391
+ if (f > 0) {
392
+ xr = data[i>>1];
393
+ xi = 0;
394
+ } else if (i == 0) {
395
+ xr = data[0];
396
+ xi = 0;
397
+ } else if (i < N) {
398
+ xr = data[i-1];
399
+ xi = data[ i ];
400
+ } else if (i == N) {
401
+ xr = data[i-1];
402
+ xi = 0;
403
+ } else {
404
+ xr = data[n-i-1];
405
+ xi =-data[ n-i ];
406
+ }
407
+ temp[j-1] = xr; temp[j] = xi;
408
+ m = (r-1) * (Nr << 1);
409
+ while (m >= 2 && j > m) {j -= m; m /= r;}
410
+ j += m / (r-1);
411
+ }
412
+ T F = -f;
413
+ T theta = 2.0 * M_PI * F / (T)r;
414
+ wqr = cos(theta); wqi = sin(theta);
415
+ mmax = 2;
416
+ while (n > mmax) {
417
+ istep = mmax * r;
418
+ wpr = cos(theta); wpi = sin(theta);
419
+ wr = 1.0; wi = 0.0;
420
+ for (m = 1; m < mmax; m += 2) {
421
+ for (i = m; i <= n; i += istep) {
422
+ for (j = i, L = 0; L < r; L++, j += mmax) {
423
+ h = (L << 1) + 1;
424
+ gw[h-1] = temp[j-1]; gw[h] = temp[j];
425
+ }
426
+ // バタフライ演算
427
+ xr = wr; xi = wi;
428
+ for (j = i, L = 0; L < r; L++, j += mmax) {
429
+ yr = yi = 0;
430
+ for (k = r; k > 0; --k) {
431
+ h = (k << 1) - 1;
432
+ relat<T>(yr, yi, xr, xi, gw[h-1], gw[h]);
433
+ } temp[j-1] = yr; temp[j] = yi;
434
+ relat<T>(xr, xi, wqr, wqi);
435
+ }
436
+ }
437
+ relat<T>(wr, wi, wpr, wpi);
438
+ }
439
+ mmax = istep;
440
+ theta /= r;
441
+ }
442
+ data[0] = temp[0];
443
+ for (i = 1; i < N; ++i) data[i] = temp[f > 0 ? i + 1 : i << 1];
444
+ delete[] gw; delete[] temp;
445
+ }
446
+ /*
447
+ 複数基数のFFT main routine
448
+ g : データ配列
449
+ N : データ個数
450
+ f : 1 forward, 0 backword, -1 invert
451
+ */
452
+ template <typename T>
453
+ bool rft(T *data, size_t N, int f)
454
+ {
455
+ size_t Nres = N, s = 0, k, n = N << 1;
456
+ size_t Ni[SDIM], ni[SDIM], M[SDIM], r[SDIM]; r[0] = 2;
457
+ // Chinese Remainder Theorem
458
+ do {
459
+ M[s] = 0; ni[s] = 1; Ni[s] = N;
460
+ while (Ni[s] % r[s] == 0) {
461
+ M[s]++;
462
+ ni[s] *= r[s]; // ni = r**M;
463
+ Ni[s] /= r[s];
464
+ } Nres /= ni[s];
465
+ int rnew;
466
+ if (Nres != 1) {
467
+ rnew = r[s] + (r[s] == 2 ? 1 : 2);
468
+ if (M[s] > 0) s++;
469
+ if (s < SDIM) {
470
+ // 素因数分解
471
+ while (Nres % rnew != 0) rnew += 2;
472
+ r[s] = rnew;
473
+ }
474
+ }
475
+ } while (Nres > 1 && s < SDIM);
476
+ int F = (f > 0) ? 1 : -1;
477
+ if (s >= SDIM) return false; else
478
+ if (s == 0) {
479
+ switch (r[s]) {
480
+ case 2: rft2<T>(data, N, F); break;
481
+ case 3: rft<T,3>(data, N, F); break;
482
+ case 5: rft<T,5>(data, N, F); break;
483
+ case 7: rft<T,7>(data, N, F); break;
484
+ default: rft<T>(r[s], data, N, F);
485
+ }
486
+ } else {
487
+ size_t smax = s + 1;
488
+ T gw[n];
489
+ // 最初の並び替え
490
+ for (k = 0; k < N; ++k) {
491
+ size_t ks, kk = 0;
492
+ T wr, wi;
493
+ for (s = 0; s < smax; ++s)
494
+ kk = kk * ni[s] + k % ni[s];
495
+ kk <<= 1; ks = k << 1;
496
+ if (F > 0) {
497
+ wr = data[k];
498
+ wi = 0;
499
+ } else if (ks == 0) {
500
+ wr = data[0];
501
+ wi = 0;
502
+ } else if (ks == N) {
503
+ wr = data[N-1];
504
+ wi = 0;
505
+ } else if (ks < N) {
506
+ wr = data[ks-1];
507
+ wi = data[ ks ];
508
+ } else {
509
+ ks = (N-k) << 1;
510
+ wr = data[ks-1];
511
+ wi =-data[ ks ];
512
+ }
513
+ gw[kk] = wr; gw[kk+1] = wi;
514
+ }
515
+ size_t step, stride = 1;
516
+ // フーリエ変換
517
+ for (k = smax; k > 0; --k) {
518
+ s = k - 1;
519
+ step = stride * ni[s];
520
+ for (size_t k1 = 0; k1 < stride; ++k1)
521
+ for (size_t k0 = k1; k0 < N; k0 += step)
522
+ cft(r[s], &gw[k0<<1], ni[s] << 1, F, stride);
523
+ stride = step;
524
+ }
525
+ // 最終の並び替え
526
+ for (k = 0; k < N; ++k) {
527
+ size_t Ls, Lu, L = 0, LL = 0;
528
+ for (s = 0; s < smax; ++s) {
529
+ Ls = k % ni[s];
530
+ LL = LL * ni[s] + Ls;
531
+ L += Ni[s] * Ls;
532
+ } Ls = (L % N);
533
+ Lu = LL << 1;
534
+ if (F > 0) {
535
+ Ls <<= 1;
536
+ if (Ls == 0) data[Ls] = gw[Lu];
537
+ else
538
+ if (Ls == N) data[Ls-1] = gw[Lu];
539
+ else
540
+ if (Ls < N) {
541
+ data[Ls-1] = gw[ Lu ];
542
+ data[ Ls ] = gw[Lu+1];
543
+ }
544
+ } else data[ Ls ] = gw[ Lu ];
545
+ }
546
+ }
547
+ if (f < 0) for (k = 0; k < N; ++k) data[k] /= N;
548
+ return true;
549
+ }
550
+
551
+ template bool cft<double>(double *, size_t, int);
552
+ template bool rft<double>(double *, size_t, int);