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,215 @@
1
+ /*******************************************************************************
2
+ 複素高速フーリエ変換(実数配列の引数)
3
+ Fast Fourier Transformation / Cooley-Tukey Method
4
+ *******************************************************************************/
5
+ template <typename T>
6
+ void wft2(varray<T>& work, const varray<T>& data, int f)
7
+ {
8
+ work[0] = data[0] + data[2]; work[2] = data[0] - data[2];
9
+ work[1] = data[1] + data[3]; work[3] = data[1] - data[3];
10
+ }
11
+
12
+ template <typename T>
13
+ void wft3(varray<T>& work, const varray<T>& data, int f)
14
+ {
15
+ const size_t A = data.atom();
16
+ const real<T> c = sqrt(real<T>(0.75, A));
17
+ varray<T> t(size_t(6), A); real<T> F = c * (double)(-f);
18
+ t[0] = data[2] + data[4]; t[2] = data[0] - 0.5 * t[0]; t[4] = F * (data[2] - data[4]);
19
+ t[1] = data[3] + data[5]; t[3] = data[1] - 0.5 * t[1]; t[5] = F * (data[3] - data[5]);
20
+ work[0] = data[0] + t[0]; work[2] = t[2] - t[5]; work[4] = t[2] + t[5];
21
+ work[1] = data[1] + t[1]; work[3] = t[3] + t[4]; work[5] = t[3] - t[4];
22
+ }
23
+
24
+ template <typename T>
25
+ void wft4(varray<T>& work, const varray<T>& data, int f)
26
+ {
27
+ const size_t A = data.atom();
28
+ varray<T> t(size_t(8), A); real<T> F = static_cast<real<T>>((double)(-f));
29
+ t[0] = data[0] + data[4]; t[2] = data[2] + data[6];
30
+ t[1] = data[1] + data[5]; t[3] = data[3] + data[7];
31
+ t[4] = data[0] - data[4]; t[6] = data[2] - data[6];
32
+ t[5] = data[1] - data[5]; t[7] = data[3] - data[7];
33
+ work[0] = t[0] + t[2]; work[2] = t[4] - F * t[7];
34
+ work[1] = t[1] + t[3]; work[3] = t[5] + F * t[6];
35
+ work[4] = t[0] - t[2]; work[6] = t[4] + F * t[7];
36
+ work[5] = t[1] - t[3]; work[7] = t[5] - F * t[6];
37
+ }
38
+
39
+ template <typename T> inline
40
+ void wft5(varray<T>& work, const varray<T>& data, int f)
41
+ {
42
+ const size_t A = data.atom();
43
+ const real<T> c0 = sqrt(real<T>(5.0, A))/4.0, c1 = sin(_2pi[A]/5.0), c2 = sin(_pi[A]/5.0);
44
+ varray<T> t(size_t(10), A), s(size_t(8), A);;
45
+ real<T> F = static_cast<real<T>>((double)(-f));
46
+ t[0] = data[2] + data[8]; t[2] = data[4] + data[6];
47
+ t[1] = data[3] + data[9]; t[3] = data[5] + data[7];
48
+ t[4] = data[2] - data[8]; t[6] = data[4] - data[6];
49
+ t[5] = data[3] - data[9]; t[7] = data[5] - data[7];
50
+ t[8] = t[0] + t[2]; s[0] = c0 * (t[0] - t[2]); s[2] = data[0] - 0.25 * t[8];
51
+ t[9] = t[1] + t[3]; s[1] = c0 * (t[1] - t[3]); s[3] = data[1] - 0.25 * t[9];
52
+ s[4] = s[2] + s[0]; s[6] = s[2] - s[0];
53
+ s[5] = s[3] + s[1]; s[7] = s[3] - s[1];
54
+ s[0] = F * (c1 * t[4] + c2 * t[6]); s[2] = F * (c2 * t[4] - c1 * t[6]);
55
+ s[1] = F * (c1 * t[5] + c2 * t[7]); s[3] = F * (c2 * t[5] - c1 * t[7]);
56
+ work[0] = data[0] + t[8];
57
+ work[1] = data[1] + t[9];
58
+ work[2] = s[4] - s[1]; work[4] = s[6] - s[3];
59
+ work[3] = s[5] + s[0]; work[5] = s[7] + s[2];
60
+ work[6] = s[6] + s[3]; work[8] = s[4] + s[1];
61
+ work[7] = s[7] - s[2]; work[9] = s[5] - s[0];
62
+ }
63
+
64
+ template <typename T>
65
+ void wft6(varray<T>& work, const varray<T>& data, int f)
66
+ {
67
+ const size_t A = data.atom();
68
+ const real<T> c = sqrt(real<T>(0.75, A));
69
+ varray<T> t(size_t(12), A), s(size_t(12), A);
70
+ real<T> F = static_cast<real<T>>((double)(-f));
71
+ s[0] = data[ 4] + data[8]; s[2] = data[0] - 0.5 * s[0]; s[ 4] = c * (data[ 4] - data[8]);
72
+ s[1] = data[ 5] + data[9]; s[3] = data[1] - 0.5 * s[1]; s[ 5] = c * (data[ 5] - data[9]);
73
+ s[6] = data[10] + data[2]; s[8] = data[6] - 0.5 * s[6]; s[10] = c * (data[10] - data[2]);
74
+ s[7] = data[11] + data[3]; s[9] = data[7] - 0.5 * s[7]; s[11] = c * (data[11] - data[3]);
75
+ t[0] = data[0] + s[0]; t[2] = s[2] + F * s[ 5]; t[ 4] = s[2] - F * s[ 5];
76
+ t[1] = data[1] + s[1]; t[3] = s[3] - F * s[ 4]; t[ 5] = s[3] + F * s[ 4];
77
+ t[6] = data[6] + s[6]; t[8] = s[8] + F * s[11]; t[10] = s[8] - F * s[11];
78
+ t[7] = data[7] + s[7]; t[9] = s[9] - F * s[10]; t[11] = s[9] + F * s[10];
79
+ work[0] = t[0] + t[6]; work[2] = t[4] - t[10]; work[ 4] = t[2] + t[8];
80
+ work[1] = t[1] + t[7]; work[3] = t[5] - t[11]; work[ 5] = t[3] + t[9];
81
+ work[6] = t[0] - t[6]; work[8] = t[4] + t[10]; work[10] = t[2] - t[8];
82
+ work[7] = t[1] - t[7]; work[9] = t[5] + t[11]; work[11] = t[3] - t[9];
83
+ }
84
+
85
+ template <typename T>
86
+ void wft(size_t r, varray<T>& work, const varray<T>& data, const real<T>& wp, const real<T>& wq)
87
+ {
88
+ size_t h, i, j, k, r2 = (r >> 1) + (r%2), A = data.atom();
89
+ real<T> ap, am, bp, bm, sw = -1.0;
90
+ varray<T> t(size_t(8), A);
91
+ work[0] = data[0]; work[1] = data[1];
92
+ for (k = 1; k < r; ++k) { i = k << 1; work[0] += data[i]; work[1] += data[i+1]; }
93
+ real<T> xr = wp, xi = wq; // W = W0 = exp(-2πi/r);
94
+ for (h = 1; h < r2; ++h) {
95
+ real<T> cw2 = 2.0 * xr;
96
+ for (i = 0; i < 8; ++i) t[i] = 0.0;
97
+ for (k = r2-1; k > 0; --k) {
98
+ i = k << 1; j = (r-k) << 1;
99
+ ap = data[ i ] + data[ j ] + t[0] * cw2 - t[4]; t[4] = t[0]; t[0] = ap;
100
+ am = data[i+1] - data[j+1] + t[2] * cw2 - t[6]; t[6] = t[2]; t[2] = am;
101
+ bp = data[i+1] + data[j+1] + t[1] * cw2 - t[5]; t[5] = t[1]; t[1] = bp;
102
+ bm = data[ i ] - data[ j ] + t[3] * cw2 - t[7]; t[7] = t[3]; t[3] = bm;
103
+ } t[6] = t[7] = 0.0;
104
+ if (r%2 == 0) { i = r2 << 1; t[6] = sw * data[i]; t[7] = sw * data[i+1]; sw *= -1.0; }
105
+ ap = data[0] + t[0] * xr - t[4] + t[6]; am = t[2] * xi;
106
+ bp = data[1] + t[1] * xr - t[5] + t[7]; bm = t[3] * xi;
107
+ relat(xr, xi, wp, wq); // W *= W0;
108
+ i = h << 1; j = (r-h) << 1;
109
+ work[i] = ap - am; work[i+1] = bp + bm;
110
+ work[j] = ap + am; work[j+1] = bp - bm;
111
+ }
112
+ if (r%2 == 0) {
113
+ sw = -1.0;
114
+ i = h << 1;
115
+ work[i] = data[0]; work[i+1] = data[1];
116
+ for (k = 1; k < r; ++k) {
117
+ j = k << 1;
118
+ work[i] += sw * data[j]; work[i+1] += sw * data[j+1];
119
+ sw *= -1.0;
120
+ }
121
+ }
122
+ }
123
+
124
+ template <typename T>
125
+ void cft(size_t *R, size_t *M, size_t o, varray<T>& data, size_t n, int f)
126
+ {
127
+ size_t l, m, r, s, N = n >> 1, A = data.atom();
128
+ real<T> wr, wi, wc, ws, wp, wq;
129
+
130
+ size_t h, i, j, k;
131
+ varray<T> work(n, A); varray<T> *w0 = &data, *w1 = &work;
132
+ real<T> F = static_cast<real<T>>((double)(-f)), K;
133
+ real<T> theta = _2pi[A] * F, theta0 = theta;
134
+ size_t Nj = 1, L, Li, Bj, Mj, Pj;
135
+ for (s = 0, l = M[0]; s < o; (--l == 0) && (l = M[++s])) {
136
+ r = R[s]; m = N / r;
137
+ K = static_cast<real<T>>((double)r);
138
+ sincos(theta0/K, wq, wp); // W0 = (wp, wq) = exp(2*PI*F/R);
139
+ Pj = Nj * r;
140
+ theta /= K;
141
+ sincos(theta, ws, wc); // W1 = (wc, ws) = exp(2*PI*F/R^j);
142
+ varray<T> &b0 = *w0, &b1 = *w1;
143
+ varray<T> &gw = *(new varray<T>(r << 1, A));
144
+ varray<T> &tw = *(new varray<T>(r << 1, A));
145
+ wr = wc; wi = ws; // WL = (wr, wi) = W1;
146
+ for (L = 0; L < Nj; ++L) {
147
+ for (Mj = L, Bj = L; Bj < N; Bj += Pj, Mj += Nj) {
148
+ i = Mj << 1;
149
+ tw[0] = b0[i]; tw[1] = b0[i+1];
150
+ real<T> xr = wr, xi = wi;
151
+ for (Li = Mj+m, k = 1; k < r; ++k, Li += m) {
152
+ i = k << 1; j = Li << 1;
153
+ if (L == 0) {
154
+ tw[i] = b0[j]; tw[i+1] = b0[j+1];
155
+ } else {
156
+ tw[ i ] = b0[j] * xr - b0[j+1] * xi;
157
+ tw[i+1] = b0[j] * xi + b0[j+1] * xr;
158
+ relat(xr, xi, wr, wi);
159
+ }
160
+ }
161
+ switch (r) {
162
+ case 2: wft2(gw, tw, f); break;
163
+ case 3: wft3(gw, tw, f); break;
164
+ case 4: wft4(gw, tw, f); break;
165
+ case 5: wft5(gw, tw, f); break;
166
+ case 6: wft6(gw, tw, f); break;
167
+ default: wft(r, gw, tw, wp, wq);
168
+ }
169
+ for (Li = Bj, h = 0; h < r; ++h, Li += Nj) {
170
+ i = Li << 1; j = h << 1;
171
+ b1[i] = gw[j]; b1[i+1] = gw[j+1];
172
+ }
173
+ }
174
+ if (L > 0) relat(wr, wi, wc, ws); // WL *= W1;
175
+ }
176
+ Nj = Pj;
177
+ delete &tw;
178
+ delete &gw;
179
+ varray<T> *w2 = w0; w0 = w1; w1 = w2;
180
+ }
181
+ if (w1 == &data) for (i = 0; i < n; ++i) data[i] = work[i];
182
+ }
183
+
184
+ #define SDIM 10
185
+ // Chinese Remainder Theorem
186
+ void crt(const size_t N, size_t& s, const size_t *r, size_t *R, size_t *Ni, size_t *M)
187
+ {
188
+ size_t Nres = N, i = 0; R[0] = r[i];
189
+ do {
190
+ Ni[s] = 1; M[s] = 0;
191
+ while (Nres % R[s] == 0) {
192
+ M[s]++;
193
+ Ni[s] *= R[s]; // Ni = R^M;
194
+ Nres /= R[s];
195
+ }
196
+ int rnew = R[s];
197
+ if (Nres != 1) {
198
+ if (M[s] > 0) s++;
199
+ if (s < SDIM) { // 素因数分解
200
+ while (Nres % rnew != 0) if (r[i] > 2) rnew = r[++i]; else rnew += (rnew == 2 ? 1 : 2);
201
+ R[s] = rnew;
202
+ }
203
+ }
204
+ } while (Nres > 1 && s < SDIM);
205
+ }
206
+
207
+ template <typename T>
208
+ bool cfft(varray<T>& data, size_t n, int f)
209
+ {
210
+ size_t s = 0, m[] = {6, 4, 2}, N = n >> 1, R[SDIM], M[SDIM], Ni[SDIM];
211
+ crt(N, s, m, R, Ni, M);
212
+ cft<T>(R, M, s+1, data, n, f > 0 ? 1 : -1);
213
+ if (f < 0) for (size_t i = 0; i < n; ++i) data[i] /= N;
214
+ return true;
215
+ }
@@ -0,0 +1,625 @@
1
+ /*******************************************************************************
2
+ 実数値高速フーリエ変換
3
+ Fast Fourier Transformation
4
+ *******************************************************************************/
5
+ template <typename T> inline
6
+ void xft2(varray<T>& work, const varray<T>& data, int f)
7
+ {
8
+ work[0] = data[0] + data[1]; work[1] = data[0] - data[1];
9
+ }
10
+
11
+ template <typename T> inline
12
+ void xft3(varray<T>& work, const varray<T>& data, int f)
13
+ {
14
+ const size_t A = data.atom();
15
+ const real<T> c = sqrt(real<T>(0.75, A));
16
+ const real<T> F = c * (double)(-f);
17
+ real<T> t1 = data[1] + data[2];
18
+ work[0] = data[0] + t1;
19
+ work[1] = data[0] - 0.5 * t1;
20
+ work[2] = F * (data[1] - data[2]);
21
+ }
22
+
23
+ template <typename T> inline
24
+ void xbt3(varray<T>& work, const varray<T>& data, int f)
25
+ {
26
+ const size_t A = data.atom();
27
+ const real<T> c = sqrt(real<T>(0.75, A));
28
+ const real<T> F = c * (double)(-f);
29
+ real<T> t1 = 2.0 * data[1];
30
+ real<T> t2 = data[0] - 0.5 * t1, t3 = 2.0 * F * data[2];
31
+ work[0] = data[0] + t1;
32
+ work[1] = t2 - t3;
33
+ work[2] = t2 + t3;
34
+ }
35
+
36
+ template <typename T> inline
37
+ void xft4(varray<T>& work, const varray<T>& data, int f)
38
+ {
39
+ real<T> F = static_cast<real<T>>((double)(-f));
40
+ real<T> t1 = data[0] + data[2], t2 = data[1] + data[3];
41
+ real<T> t3 = data[0] - data[2], t4 = data[1] - data[3];
42
+ work[0] = t1 + t2; work[1] = t3;
43
+ work[2] = t1 - t2; work[3] = F * t4;
44
+ }
45
+
46
+ template <typename T> inline
47
+ void xbt4(varray<T>& work, const varray<T>& data, int f)
48
+ {
49
+ real<T> F = static_cast<real<T>>((double)(-f));
50
+ real<T> t1 = data[0] + data[2], t2 = 2.0 * data[1];
51
+ real<T> t3 = data[0] - data[2], t4 = 2.0 * data[3] * F;
52
+ work[0] = t1 + t2; work[1] = t3 - t4;
53
+ work[2] = t1 - t2; work[3] = t3 + t4;
54
+ }
55
+
56
+ template <typename T> inline
57
+ void xft5(varray<T>& work, const varray<T>& data, int f)
58
+ {
59
+ const size_t A = data.atom();
60
+ const real<T> c0 = sqrt(real<T>(5.0, A))/4.0, c1 = sin(_2pi[A]/5.0), c2 = sin(_pi[A]/5.0);
61
+ varray<T> t(size_t(7), A);
62
+ real<T> F = static_cast<real<T>>((double)(-f));
63
+ t[0] = data[1] + data[4]; t[2] = data[2] + data[3];
64
+ t[1] = data[1] - data[4]; t[3] = data[2] - data[3];
65
+ t[4] = t[0] + t[2]; t[5] = data[0] - 0.25 * t[4]; t[6] = c0 * (t[0] - t[2]);
66
+ work[0] = data[0] + t[4];
67
+ work[1] = t[5] + t[6]; work[4] = F * (c1 * t[1] + c2 * t[3]);
68
+ work[2] = t[5] - t[6]; work[3] = F * (c2 * t[1] - c1 * t[3]);
69
+ }
70
+
71
+ template <typename T> inline
72
+ void xbt5(varray<T>& work, const varray<T>& data, int f)
73
+ {
74
+ const size_t A = data.atom();
75
+ const real<T> c0 = sqrt(real<T>(5.0, A))/4.0, c1 = sin(_2pi[A]/5.0), c2 = sin(_pi[A]/5.0);
76
+ varray<T> t(size_t(9), A);
77
+ real<T> F = static_cast<real<T>>((double)(-f));
78
+ t[0] = 2.0 * data[1]; t[2] = 2.0 * data[2];
79
+ t[1] = 2.0 * data[4]; t[3] = 2.0 * data[3];
80
+ t[4] = t[0] + t[2]; t[5] = data[0] - 0.25 * t[4]; t[6] = c0 * (t[0] - t[2]);
81
+ t[0] = t[5] + t[6]; t[7] = F * (c1 * t[1] + c2 * t[3]);
82
+ t[2] = t[5] - t[6]; t[8] = F * (c2 * t[1] - c1 * t[3]);
83
+ work[0] = data[0] + t[4];
84
+ work[1] = t[0] - t[7]; work[2] = t[2] - t[8];
85
+ work[4] = t[0] + t[7]; work[3] = t[2] + t[8];
86
+ }
87
+
88
+ template <typename T> inline
89
+ void xft6(varray<T>& work, const varray<T>& data, int f)
90
+ {
91
+ const size_t A = data.atom();
92
+ const real<T> c = sqrt(real<T>(0.75, A));
93
+ varray<T> t(size_t(6), A);
94
+ real<T> F = c * (double)(-f);
95
+ t[0] = data[2] + data[4]; t[2] = data[0] - 0.5 * t[0]; t[4] = data[2] - data[4];
96
+ t[1] = data[5] + data[1]; t[3] = data[3] - 0.5 * t[1]; t[5] = data[5] - data[1];
97
+ t[0] += data[0]; t[1] += data[3];
98
+ work[0] = t[0] + t[1];
99
+ work[1] = t[2] - t[3]; work[5] = F * (t[4] - t[5]);
100
+ work[2] = t[2] + t[3]; work[4] = -F * (t[4] + t[5]);
101
+ work[3] = t[0] - t[1];
102
+ }
103
+
104
+ template <typename T> inline
105
+ void xbt6(varray<T>& work, const varray<T>& data, int f)
106
+ {
107
+ const size_t A = data.atom();
108
+ const real<T> c = sqrt(real<T>(0.75, A));
109
+ varray<T> t(size_t(10), A);
110
+ real<T> F = c * (double)(-f);
111
+ t[0] = 2.0 * data[2]; t[2] = data[0] - data[2]; t[4] = 2.0 * F * data[4];
112
+ t[1] = 2.0 * data[1]; t[3] = data[3] - data[1]; t[5] = 2.0 * F * data[5];
113
+ t[6] = t[2] - t[4]; t[8] = t[3] + t[5];
114
+ t[7] = t[2] + t[4]; t[9] = t[3] - t[5];
115
+ t[0] += data[0]; t[1] += data[3];
116
+ work[0] = t[0] + t[1]; work[1] = t[6] - t[8]; work[2] = t[7] + t[9];
117
+ work[3] = t[0] - t[1]; work[4] = t[6] + t[8]; work[5] = t[7] - t[9];
118
+ }
119
+
120
+ template <typename T>
121
+ void xft(size_t r, varray<T>& work, const varray<T>& data, const real<T>& wp, const real<T>& wq)
122
+ {
123
+ size_t i, j, k, r2 = (r >> 1) + (r%2), A = data.atom();
124
+ real<T> xr = wp, xi = wq, sw = -1.0; // W = (xr, xi) = W0;
125
+ varray<T> w(size_t(6), A);
126
+ work[0] = data[0]; for (i = 1; i < r; ++i) work[0] += data[i];
127
+ for (i = 1; i < r2; ++i) {
128
+ real<T> cw2 = 2.0 * xr;
129
+ for (j = 0; j < 4; ++j) w[j] = 0.0;
130
+ for (j = r2-1; j > 0; --j) {
131
+ w[4] = data[j] + data[r-j] + w[0] * cw2 - w[2]; w[2] = w[0]; w[0] = w[4];
132
+ w[5] = data[j] - data[r-j] + w[1] * cw2 - w[3]; w[3] = w[1]; w[1] = w[5];
133
+ } w[3] = 0.0;
134
+ if (r%2 == 0) { w[3] = sw * data[r2]; sw *= -1.0; }
135
+ work[i] = data[0] + w[0] * xr - w[2] + w[3]; work[r-i] = w[1] * xi;
136
+ relat(xr, xi, wp, wq);
137
+ }
138
+ if (r%2 == 0) {
139
+ work[i] = data[0];
140
+ for (k = 1; k < r; ++k)
141
+ if (k%2) work[i] -= data[k];
142
+ else work[i] += data[k];
143
+ }
144
+ }
145
+
146
+ template <typename T>
147
+ void xbt(size_t r, varray<T>& work, const varray<T>& data, const real<T>& wp, const real<T>& wq)
148
+ {
149
+ size_t i, j, r2 = (r >> 1) + (r%2), A = data.atom();
150
+ real<T> sw = -1.0, cw = 2.0;
151
+ varray<T> w(size_t(6), A);
152
+ work[0] = data[0];
153
+ for (j = 1; j < r2; ++j) {
154
+ work[0] += cw * data[j];
155
+ }
156
+ if (r%2 == 0) {
157
+ work[0] += data[j];
158
+ }
159
+ real<T> wr = wp, wi = wq; // W = (wr, wi) = W0;
160
+ for (i = 1; i < r2; ++i) {
161
+ real<T> cw2 = 2.0 * wr;
162
+ for (j = 0; j < 4; ++j) w[j] = 0.0;
163
+ for (j = r2-1; j > 0; --j) {
164
+ w[4] = data[ j ] * cw + w[0] * cw2 - w[2]; w[2] = w[0]; w[0] = w[4];
165
+ w[5] = data[r-j] * cw + w[1] * cw2 - w[3]; w[3] = w[1]; w[1] = w[5];
166
+ } w[3] = (r%2) ? 0.0 : sw * data[r2];
167
+ w[4] = data[0] + w[0] * wr - w[2] + w[3]; w[5] = w[1] * wi;
168
+ work[i] = w[4] - w[5]; work[r-i] = w[4] + w[5];
169
+ relat(wr, wi, wp, wq); // W *= W0;
170
+ sw *= -1.0;
171
+ }
172
+ if (r%2 == 0) {
173
+ sw = -cw;
174
+ work[i] = data[0];
175
+ for (j = 1; j < r2; ++j) {
176
+ work[i] += sw * data[j];
177
+ sw *= -1.0;
178
+ }
179
+ work[i] += 0.5 * sw * data[j];
180
+ }
181
+ }
182
+
183
+ template <typename T> inline
184
+ void zft2(varray<T>& work, const varray<T>& data, int f)
185
+ {
186
+ real<T> F = static_cast<real<T>>((double)(-f));
187
+ work[0] = data[0]; work[1] = F * data[1];
188
+ }
189
+
190
+ template <typename T> inline
191
+ void zbt2(varray<T>& work, const varray<T>& data, int f)
192
+ {
193
+ real<T> F = static_cast<real<T>>((double)(-f));
194
+ work[0] = 2.0 * data[0]; work[1] = -2.0 * F * data[1];
195
+ }
196
+
197
+ template <typename T> inline
198
+ void zft3(varray<T>& work, const varray<T>& data, int f)
199
+ {
200
+ const size_t A = data.atom();
201
+ const real<T> c = sqrt(real<T>(0.75, A));
202
+ real<T> F = c * (double)(-f);
203
+ real<T> t = data[1] - data[2];
204
+ work[0] = data[0] + 0.5 * t;
205
+ work[1] = data[0] - t;
206
+ work[2] = F * (data[1] + data[2]);
207
+ }
208
+
209
+ template <typename T> inline
210
+ void zbt3(varray<T>& work, const varray<T>& data, int f)
211
+ {
212
+ const size_t A = data.atom();
213
+ static const real<T> c = sqrt(real<T>(3.0, A));
214
+ real<T> F = c * (double)(-f);
215
+ real<T> t1 = data[0] - data[1], t2 = F * data[2];
216
+ work[0] = 2.0 * data[0] + data[1];
217
+ work[1] = t1 - t2;
218
+ work[2] = -t1 - t2;
219
+ }
220
+
221
+ template <typename T> inline
222
+ void zft4(varray<T>& work, const varray<T>& data, int f)
223
+ {
224
+ const size_t A = data.atom();
225
+ static const real<T> c = sqrt(real<T>(2.0, A));
226
+ real<T> F = c * (double)(-f);
227
+ real<T> t1 = (data[1] - data[3]) / F, t2 = (data[1] + data[3]) / F;
228
+ work[0] = data[0] - t1; work[3] = t2 - data[2];
229
+ work[1] = data[0] + t1; work[2] = t2 + data[2];
230
+ }
231
+
232
+ template <typename T> inline
233
+ void zbt4(varray<T>& work, const varray<T>& data, int f)
234
+ {
235
+ const size_t A = data.atom();
236
+ const real<T> c = sqrt(real<T>(2.0, A));
237
+ real<T> F = c * (double)(-f);
238
+ real<T> t1 = F * (data[3] + data[2]), t2 = F * (data[0] - data[1]);
239
+ work[0] = 2.0 * (data[0] + data[1]); work[1] = t2 - t1;
240
+ work[2] = 2.0 * (data[2] - data[3]); work[3] = -t2 - t1;
241
+ }
242
+
243
+ template <typename T> inline
244
+ void zft5(varray<T>& work, const varray<T>& data, int f)
245
+ {
246
+ const size_t A = data.atom();
247
+ const real<T> c0 = sqrt(real<T>(5.0, A))/4.0, c1 = sin(_2pi[A]/5.0), c2 = sin(_pi[A]/5.0);
248
+ varray<T> t(size_t(7), A);
249
+ real<T> F = static_cast<real<T>>((double)(-f));
250
+ t[0] = data[1] - data[4]; t[1] = data[1] + data[4];
251
+ t[2] = data[2] - data[3]; t[3] = data[2] + data[3];
252
+ t[4] = t[0] - t[2]; t[5] = data[0] + 0.25 * t[4]; t[6] = c0 * (t[0] + t[2]);
253
+ work[0] = t[5] + t[6]; work[4] = F * (c2 * t[1] + c1 * t[3]);
254
+ work[1] = t[5] - t[6]; work[3] = F * (c1 * t[1] - c2 * t[3]);
255
+ work[2] = data[0] - t[4];
256
+ }
257
+
258
+ template <typename T> inline
259
+ void zbt5(varray<T>& work, const varray<T>& data, int f)
260
+ {
261
+ const size_t A = data.atom();
262
+ const real<T> c0 = sqrt(real<T>(5.0, A))/2.0, c1 = sin(_2pi[A]/5.0), c2 = sin(_pi[A]/5.0);
263
+ varray<T> t(size_t(7), A);
264
+ real<T> F = static_cast<real<T>>((double)(-f));
265
+ t[0] = 2.0 * (data[0] + data[1]); t[1] = 0.25 * t[0] - data[2];
266
+ t[2] = c0 * (data[0] - data[1]);
267
+ t[3] = 2.0 * F * (c2 * data[4] + c1 * data[3]);
268
+ t[4] = 2.0 * F * (c1 * data[4] - c2 * data[3]);
269
+ t[5] = t[2] + t[1]; t[6] = t[2] - t[1];
270
+ work[0] = t[0] + data[2];
271
+ work[1] = t[5] - t[3]; work[4] = -(t[5] + t[3]);
272
+ work[2] = t[6] - t[4]; work[3] = -(t[6] + t[4]);
273
+ }
274
+
275
+ template <typename T> inline
276
+ void zft6(varray<T>& work, const varray<T>& data, int f)
277
+ {
278
+ const size_t A = data.atom();
279
+ const real<T> c = sqrt(real<T>(0.75, A));
280
+ varray<T> t(size_t(6), A);
281
+ real<T> F = static_cast<real<T>>((double)(-f));
282
+ t[0] = c * (data[5] - data[1]); t[2] = data[2] - data[4];
283
+ t[1] = c * (data[2] + data[4]); t[3] = data[1] + data[5];
284
+ t[4] = data[0] + 0.5 * t[2]; t[5] = - data[3] - 0.5 * t[3];
285
+ work[0] = t[4] + F * t[0]; work[1] = data[0] - t[2]; work[2] = t[4] - F * t[0];
286
+ work[5] = t[5] + F * t[1]; work[4] = data[3] - t[3]; work[3] = t[5] - F * t[1];
287
+ }
288
+
289
+ template <typename T>
290
+ void zft(size_t r, varray<T>& work, const varray<T>& data, const real<T>& wr, const real<T>& wi, const real<T>& wp, const real<T>& wq)
291
+ {
292
+ size_t i, j, r2 = r >> 1, A = data.atom(); // r2 = r/2
293
+ real<T> xr = wr, xi = wi;
294
+ varray<T> w(size_t(3), A);
295
+ for (i = 0; i < r2; ++i) { // W = (xr, xi) = WL;
296
+ real<T> cw2 = 2.0 * xr; w[0] = w[1] = 0.0;
297
+ for (j = r-1; j > 0; --j) {
298
+ w[2] = data[j] + w[0] * cw2 - w[1]; w[1] = w[0]; w[0] = w[2];
299
+ }
300
+ work[i] = data[0] + w[0] * xr - w[1]; work[r-1-i] = w[0] * xi;
301
+ relat(xr, xi, wp, wq); // W *= W0;
302
+ }
303
+ if (r%2) { // i == r/2;
304
+ work[i] = data[0];
305
+ for (j = 1; j < r; ++j)
306
+ if (j%2 == 0) work[i] += data[j]; else work[i] -= data[j];
307
+ }
308
+ }
309
+
310
+ template <typename T>
311
+ void zbt(size_t r, varray<T>& work, const varray<T>& data, const real<T>& wr, const real<T>& wi, const real<T>& wp, const real<T>& wq)
312
+ {
313
+ size_t i, j, k, r2 = r >> 1, A = data.atom(); // r2 = r/2
314
+ work[0] = data[0] * 2.0;
315
+ for (k = 1; k < r2; ++k) {
316
+ work[0] += data[k] * 2.0;
317
+ }
318
+ if (r%2) {
319
+ work[0] += data[k];
320
+ }
321
+ real<T> xr = wp, xi = wq, yr = wr, yi = wi;
322
+ varray<T> w(size_t(6), A);
323
+ for (i = 1; i < r; ++i) {
324
+ real<T> cw2 = 2.0 * xr;
325
+ for (j = 0; j < 4; ++j) w[j] = 0.0;
326
+ for (k = r-1; k > 0; --k) {
327
+ bool g = (k == r2) && (r%2);
328
+ j = r-1-k;
329
+ w[4] = data[k < r2 || g ? k : j];
330
+ w[5] = k < r2 ? data[j] : g ? 0.0 : -data[k];
331
+ w[4] = w[4] + w[0] * cw2 - w[2]; w[2] = w[0]; w[0] = w[4];
332
+ w[5] = w[5] + w[1] * cw2 - w[3]; w[3] = w[1]; w[1] = w[5];
333
+ } w[4] = data[ 0 ] + w[0] * xr - w[1] * xi - w[2];
334
+ w[5] = data[r-1] + w[0] * xi + w[1] * xr - w[3];
335
+ relat(xr, xi, wp, wq); // W *= W0;
336
+ work[i] = w[4] * yr - w[5] * yi;
337
+ relat(yr, yi, wr, wi); // WL *= W1^L;
338
+ }
339
+ }
340
+
341
+ template <typename T>
342
+ void rsft(size_t *R, size_t *M, size_t n, varray<T>& data, size_t N, int f = 1)
343
+ {
344
+ size_t l, m, r, s, A = data.atom();
345
+ real<T> wr, wi, wp, wq, wc, ws;
346
+
347
+ size_t i, k;
348
+ real<T> F = static_cast<real<T>>((double)(-f)), K;
349
+ real<T> theta0 = _2pi[A] * F, theta = theta0;
350
+ varray<T> work(N, A); varray<T> *w0 = &data, *w1 = &work;
351
+ size_t Nj = 1, L, Li, Lj, Bj, Mj, Pj, Wi, Wj; // Nj = R^(j-1); j = 1...M
352
+ for (s = 0, l = M[0]; s < n; (--l == 0) && (l = M[++s])) {
353
+ r = R[s]; m = N / r;
354
+ K = static_cast<real<T>>((double)r);
355
+ theta /= K;
356
+ sincos(theta0/K, wq, wp); // W0 = (wp, wq) = exp(2*PI*F/R);
357
+ Pj = Nj * r;
358
+ sincos(theta, ws, wc); // W1 = (wc, ws) = exp(2*PI*F/R^j);
359
+ varray<T> &b0 = *w0; varray<T> &b1 = *w1;
360
+ varray<T> &gw = *(new varray<T>(r << 1, A));
361
+ varray<T> &tw = *(new varray<T>(r << 1, A));
362
+ for (Bj = 0, Mj = 0; Bj < N; Mj += Nj, Bj += Pj) {
363
+ for (Li = Mj, i = 0; i < r; ++i, Li += m) {
364
+ tw[i] = b0[Li];
365
+ }
366
+ switch (r) {
367
+ case 2: xft2(gw, tw, f); break;
368
+ case 3: xft3(gw, tw, f); break;
369
+ case 4: xft4(gw, tw, f); break;
370
+ case 5: xft5(gw, tw, f); break;
371
+ case 6: xft6(gw, tw, f); break;
372
+ default: xft(r, gw, tw, wp, wq);
373
+ }
374
+ b1[Bj] = gw[0];
375
+ for (Li = Nj, Lj = Pj-Nj, k = 1; Li < Lj; ++k, Lj -= Nj, Li += Nj) {
376
+ #ifdef FFTPACK
377
+ Wi = (Li < Lj) ? Li : Lj; Wj = Bj + (Wi << 1); Wi = Wj - 1;
378
+ #else
379
+ Wi = Bj + Li; Wj = Bj + Lj;
380
+ #endif
381
+ b1[Wi] = gw[k]; b1[Wj] = gw[r-k];
382
+ }
383
+ if (Li == Lj) {
384
+ #ifdef FFTPACK
385
+ Wi = Bj + (Li << 1) - 1;
386
+ #else
387
+ Wi = Bj + Li;
388
+ #endif
389
+ b1[Wi] = gw[k];
390
+ }
391
+ }
392
+ wr = wc; wi = ws; // WL = (wr, wi) = W1;
393
+ for (L = 1; L <= Nj/2; ++L) {
394
+ for (Mj = 0, Bj = 0; Bj < N; Bj += Pj, Mj += Nj) {
395
+ if (Nj%2 || L < Nj/2) {
396
+ real<T> xr = wr, xi = wi; // W = (xr, xi) = WL;
397
+ #ifdef FFTPACK
398
+ Lj = Mj + (L << 1); Li = Lj - 1;
399
+ #else
400
+ Li = Mj + L; Lj = Mj + Nj - L;
401
+ #endif
402
+ tw[0] = b0[Li]; tw[1] = b0[Lj];
403
+
404
+ for (Li = Mj+m, i = 1; i < r; ++i, Li += m) {
405
+ #ifdef FFTPACK
406
+ Wj = Li + (L << 1); Wi = Wj - 1;
407
+ #else
408
+ Wi = Li + L; Wj = Li + Nj - L;
409
+ #endif
410
+ k = i << 1;
411
+ tw[ k ] = b0[Wi] * xr - b0[Wj] * xi;
412
+ tw[k+1] = b0[Wi] * xi + b0[Wj] * xr;
413
+ relat(xr, xi, wr, wi); // W *= WL;
414
+ }
415
+ switch (r) {
416
+ case 2: wft2(gw, tw, f); break;
417
+ case 3: wft3(gw, tw, f); break;
418
+ case 4: wft4(gw, tw, f); break;
419
+ case 5: wft5(gw, tw, f); break;
420
+ case 6: wft6(gw, tw, f); break;
421
+ default: wft(r, gw, tw, wp, wq);
422
+ }
423
+ for (Li = L, Lj = Pj-L, i = 0; i < r; ++i, Lj -= Nj, Li += Nj) {
424
+ #ifdef FFTPACK
425
+ if (Li < Lj) { Wj = Bj + (Li << 1); Wi = Wj - 1; }
426
+ else { Wi = Bj + (Lj << 1); Wj = Wi - 1; }
427
+ #else
428
+ Wi = Bj + Li; Wj = Bj + Lj;
429
+ #endif
430
+ k = i << 1;
431
+ if (Li < Lj) {
432
+ b1[Wi] = gw[k]; b1[Wj] = gw[k+1];
433
+ } else {
434
+ b1[Wj] = gw[k]; b1[Wi] = -gw[k+1];
435
+ }
436
+ }
437
+ } else { // L == Nj/2;
438
+ for (Li = Mj, i = 0; i < r; ++i, Li += m) {
439
+ #ifdef FFTPACK
440
+ Wi = Li + (L << 1) - 1;
441
+ #else
442
+ Wi = Li + L;
443
+ #endif
444
+ tw[i] = b0[Wi];
445
+ }
446
+ switch (r) {
447
+ case 2: zft2(gw, tw, f); break;
448
+ case 3: zft3(gw, tw, f); break;
449
+ case 4: zft4(gw, tw, f); break;
450
+ case 5: zft5(gw, tw, f); break;
451
+ case 6: zft6(gw, tw, f); break;
452
+ default: zft(r, gw, tw, wr, wi, wp, wq);
453
+ }
454
+ for (Li = L, Lj = Pj-L, k = 0; Li < Lj; ++k, Lj -= Nj, Li += Nj) {
455
+ #ifdef FFTPACK
456
+ Wj = Bj + (Li << 1); Wi = Wj - 1;
457
+ #else
458
+ Wi = Bj + Li; Wj = Bj + Lj;
459
+ #endif
460
+ b1[Wi] = gw[k]; b1[Wj] = gw[r-1-k];
461
+ }
462
+ if (Li == Lj) {
463
+ #ifdef FFTPACK
464
+ Wi = Bj + (Li << 1) - 1;
465
+ #else
466
+ Wi = Bj + Li;
467
+ #endif
468
+ b1[Wi] = gw[k];
469
+ }
470
+ }
471
+ }
472
+ relat(wr, wi, wc, ws); // WL *= W1;
473
+ }
474
+ Nj = Pj;
475
+ delete &tw;
476
+ delete &gw;
477
+ varray<T> *w2 = w0; w0 = w1; w1 = w2;
478
+ }
479
+ if (w0 != &data) for (i = 0; i < N; ++i) data[i] = work[i];
480
+ }
481
+
482
+ template <typename T>
483
+ void rbft(size_t *R, size_t *M, size_t n, varray<T>& data, size_t N, int f = -1)
484
+ {
485
+ size_t l, m, r, s, A = data.atom();
486
+ real<T> wr, wi, wp, wq, wc, ws;
487
+
488
+ size_t i, k;
489
+ real<T> F = static_cast<real<T>>((double)(-f)), K;
490
+ real<T> theta0 = _2pi[A] * F, theta = theta0 / N;
491
+ varray<T> work(N, A); varray<T> *w0 = &data, *w1 = &work;
492
+ size_t Pj = N, L, Li, Lj, Bj, Nj, Mj, Wi, Wj; // Pj = R^j; j = M...1
493
+ for (s = n, l = M[n-1]; s > 0; (--l == 0) && (l = M[--s-1])) {
494
+ r = R[s-1]; m = N / r;
495
+ K = static_cast<real<T>>((double)r);
496
+ sincos(theta0/K, wq, wp); // W0 = (wp, wq) = exp(2*PI*F/R);
497
+ Nj = Pj / r;
498
+ sincos(theta, ws, wc); // W1 = (wc, ws) = exp(2*PI*F/R^j);
499
+ varray<T> &b0 = *w0; varray<T> &b1 = *w1;
500
+ varray<T> &gw = *(new varray<T>(r << 1, A));
501
+ varray<T> &tw = *(new varray<T>(r << 1, A));
502
+ for (Bj = 0, Mj = 0; Bj < N; Bj += Pj, Mj += Nj) {
503
+ tw[0] = b0[Bj];
504
+ for (Li = Nj, Lj = Pj-Nj, k = 1; Li < Lj; ++k, Lj -= Nj, Li += Nj) {
505
+ #ifdef FFTPACK
506
+ Wi = (Li < Lj) ? Li : Lj; Wj = Bj + (Wi << 1); Wi = Wj - 1;
507
+ #else
508
+ Wi = Bj + Li; Wj = Bj + Lj;
509
+ #endif
510
+ tw[k] = b0[Wi]; tw[r-k] = b0[Wj];
511
+ }
512
+ if (Li == Lj) {
513
+ #ifdef FFTPACK
514
+ Wi = Bj + (Li << 1) - 1;
515
+ #else
516
+ Wi = Bj + Li;
517
+ #endif
518
+ tw[k] = b0[Wi];
519
+ }
520
+ switch (r) {
521
+ case 2: xft2(gw, tw, f); break;
522
+ case 3: xbt3(gw, tw, f); break;
523
+ case 4: xbt4(gw, tw, f); break;
524
+ case 5: xbt5(gw, tw, f); break;
525
+ case 6: xbt6(gw, tw, f); break;
526
+ default: xbt(r, gw, tw, wp, wq);
527
+ }
528
+ for (Li = Mj, i = 0; i < r; ++i, Li += m) b1[Li] = gw[i];
529
+ }
530
+ wr = wc; wi = ws;
531
+ for (L = 1; L <= Nj/2; ++L) {
532
+ for (Mj = 0, Bj = 0; Bj < N; Bj += Pj, Mj += Nj) {
533
+ real<T> yr = wr, yi = wi; // WL = (yr, yi) = W1;
534
+ if (Nj%2 || L < Nj/2) {
535
+ for (Li = L, Lj = Pj-L, i = 0; i < r; ++i, Li += Nj, Lj -= Nj) {
536
+ #ifdef FFTPACK
537
+ if (Li < Lj) { Wj = Bj + (Li << 1); Wi = Wj - 1; }
538
+ else { Wi = Bj + (Lj << 1); Wj = Wi - 1; }
539
+ #else
540
+ Wi = Bj + Li; Wj = Bj + Lj;
541
+ #endif
542
+ k = i << 1;
543
+ if (Li < Lj) { tw[k] = b0[Wi]; tw[k+1] = b0[Wj]; }
544
+ else { tw[k] = b0[Wj]; tw[k+1] = -b0[Wi]; }
545
+ }
546
+ switch (r) {
547
+ case 2: wft2(gw, tw, f); break;
548
+ case 3: wft3(gw, tw, f); break;
549
+ case 4: wft4(gw, tw, f); break;
550
+ case 5: wft5(gw, tw, f); break;
551
+ case 6: wft6(gw, tw, f); break;
552
+ default: wft(r, gw, tw, wp, wq);
553
+ }
554
+ #ifdef FFTPACK
555
+ Lj = Mj + (L << 1); Li = Lj - 1;
556
+ #else
557
+ Li = Mj + L; Lj = Mj + Nj - L;
558
+ #endif
559
+ b1[Li] = gw[0]; b1[Lj] = gw[1];
560
+ for (Li = Mj+m, i = 1; i < r; ++i, Li += m) {
561
+ #ifdef FFTPACK
562
+ Wj = Li + (L << 1); Wi = Wj - 1;
563
+ #else
564
+ Wi = Li + L; Wj = Li + Nj - L;
565
+ #endif
566
+ k = i << 1;
567
+ b1[Wi] = gw[k] * yr - gw[k+1] * yi;
568
+ b1[Wj] = gw[k] * yi + gw[k+1] * yr;
569
+ relat(yr, yi, wr, wi); // WL *= W1^L;
570
+ }
571
+ } else {
572
+ for ( Li = L, Lj = Pj-L, k = 0; Li < Lj; ++k, Lj -= Nj, Li += Nj) {
573
+ #ifdef FFTPACK
574
+ Wj = Bj + (Li << 1); Wi = Wj - 1;
575
+ #else
576
+ Wi = Bj + Li; Wj = Bj + Lj;
577
+ #endif
578
+ tw[k] = b0[Wi]; tw[r-1-k] = b0[Wj];
579
+ }
580
+ if (Li == Lj) {
581
+ #ifdef FFTPACK
582
+ Wi = Bj + (Li << 1) - 1;
583
+ #else
584
+ Wi = Bj + Li;
585
+ #endif
586
+ tw[k] = b0[Wi];
587
+ }
588
+ switch (r) {
589
+ case 2: zbt2(gw, tw, f); break;
590
+ case 3: zbt3(gw, tw, f); break;
591
+ case 4: zbt4(gw, tw, f); break;
592
+ case 5: zbt5(gw, tw, f); break;
593
+ default: zbt(r, gw, tw, wr, wi, wp, wq);
594
+ }
595
+ for (Li = Mj, i = 0; i < r; ++i, Li += m) {
596
+ #ifdef FFTPACK
597
+ Wi = Li + (L << 1) - 1;
598
+ #else
599
+ Wi = Li + L;
600
+ #endif
601
+ b1[Wi] = gw[i];
602
+ }
603
+ }
604
+ }
605
+ relat(wr, wi, wc, ws); // WL *= W1;
606
+ }
607
+ theta *= K;
608
+ Pj = Nj;
609
+ delete &tw;
610
+ delete &gw;
611
+ varray<T> *w2 = w0; w0 = w1; w1 = w2;
612
+ }
613
+ if (w0 != &data) for (i = 0; i < N; ++i) data[i] = work[i];
614
+ }
615
+
616
+ template <typename T>
617
+ bool rfft(varray<T>& data, size_t N, int f)
618
+ {
619
+ size_t s = 0, m[] = {2}, R[SDIM], M[SDIM], Ni[SDIM];
620
+ crt(N, s, m, R, Ni, M);
621
+ if (f > 0) rsft<T>(R, M, s+1, data, N);
622
+ else rbft<T>(R, M, s+1, data, N);
623
+ if (f < 0) for (size_t i = 0; i < N; ++i) data[i] /= N;
624
+ return true;
625
+ }