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
@@ -1,137 +1,145 @@
1
- #ifndef _BASIS_H_INCLUDED_
2
- #define _BASIS_H_INCLUDED_
3
- #include <stdlib.h>
4
- #include <string.h>
5
-
6
- template <typename T>
7
- int deboor(int, T*, int, T, T*, int&, int = 0);
8
- template<typename T>
9
- void deboor_cox(int, T*, int, T, T*, int&, int, int = 0);
10
-
11
- /*******************************************************************************
12
- Bスプライン基底(節点列によるBスプライン関数計算)
13
- *******************************************************************************/
14
- template <typename S = double> class base_spline
15
- {
16
- protected:
17
- int imax, icox, rank, jisu, shuki, maxq;
18
- S *knots;
19
- public:
20
- // constructor
21
- base_spline() : knots(NULL) {}
22
- base_spline(int, const S*, int, int = 0, int* = NULL);
23
- base_spline(const S*, int, int, int);
24
- base_spline(const base_spline&);
25
- // destructor
26
- ~base_spline() { delete[] knots; }
27
- // operator
28
- base_spline& operator=(const base_spline&);
29
- int ranks(int b=0) const {return rank-b;}
30
- int Imax() const { return imax; }
31
- int Icox() const { return icox; }
32
- int Rank() const { return rank; }
33
- int Jisu() const { return jisu; }
34
- int Shuki()const { return shuki;}
35
- int Maxq() const { return maxq; }
36
- S *Knots() const { return knots;}
37
- int Kset(S x) const;
38
- S x_max() const {return knots[icox];}
39
- S x_min() const {return knots[jisu];}
40
- S operator[] (int i) const {return knots[i];}
41
- int basic(S, int, S*, int = 0) const;
42
- void bibun_keisu(int, int, S**) const;
43
- void sekibun_keisu(int, int, S**) const;
44
- void gyoretu(S**, int, const S* = NULL, const int* = NULL) const;
45
- parray<S> basis(S, int = 0) const;
46
- parray<S> bases(S, int = 0) const;
47
- /*******************************************************************************
48
- 線形結合係数の適用 Σa[i]*b[i]; i = kset-Kai+1,...,kset;
49
- d: d > 0 ? 微分階数 : d == 0 ? 補間値
50
- t: データ点の座標値
51
- alp: 線形結合係数の配列
52
- *******************************************************************************/
53
- template <typename T> T apply(S t, T *alp, int d = 0) const
54
- {
55
- int k = rank - d;
56
- S *b = T_ALLOC(S, icox);
57
- int kset = basic(t, icox, b, k);
58
- k = kset - k + 1;
59
- if (k < 0) k = 0;
60
- T sum = 0.0;
61
- for (int i = k; i <= kset; i++) sum += alp[i] * b[i];
62
- FREE(b);
63
- return sum;
64
- }
65
- /*******************************************************************************
66
- 定積分の計算
67
- *******************************************************************************/
68
- template <typename T> T sekibun(S x, T *alp) const
69
- {
70
- S *q = knots;
71
- int K = rank, J = K - 1;
72
- int Imax = Kset(x);
73
- T sum = 0.0;
74
- for (int ql = J; ql <= Imax; ++ql) {
75
- S t = q[ql];
76
- parray<S> fl = bases(t, J);
77
- int ks = fl(0), kt = fl(1), kset = ks + J;
78
- S *ft = *fl, Qh = (ql < Imax ? q[ql+1] : x) - t;
79
- for (int i = ks; i <= kset; ++i) {
80
- S Qs = 0.0; int j = i - ks + K * kt;
81
- for (int r = K; r > 0; --r) {
82
- S Bik = ft[j -= kt];
83
- Qs = (Qs + Bik) * Qh / (S)r;
84
- }
85
- sum += alp[i] * Qs;
86
- }
87
- }
88
- return sum;
89
- }
90
- /*******************************************************************************
91
- 高階積分の計算
92
- *******************************************************************************/
93
- template <typename T> T sekibun(S t, const T *alp, int Jsk) const
94
- {
95
- int ks, kset, k = rank + Jsk;
96
- S b[k];
97
- ks = deboor<S>(rank, knots, icox, t, b, kset, k);
98
- T *a[2], *w = new T[2*(kset+1)]; a[0] = w; a[1] = &w[kset+1];
99
- for (int i = 0; i <= kset; ++i) a[Jsk%2][i] = alp[i];
100
- while (Jsk) {
101
- T *a0 = a[Jsk%2], *a1 = a[(Jsk+1)%2];
102
- for (int i = 0; i <= kset; ++i)
103
- a1[i] = (i > 0 ? a1[i-1] : 0.0) + a0[i] * (knots[i+(k-Jsk)] - knots[i]) / (k-Jsk);
104
- Jsk--;
105
- }
106
- T sek = 0.0;
107
- for (int i = ks > 0 ? ks : 0; i <= kset; ++i) sek += a[0][i] * b[i-ks];
108
- delete[] w;
109
- return sek;
110
- }
111
- /*******************************************************************************
112
- 多次元積分の計算
113
- *******************************************************************************/
114
- template <typename T> void sekibun(S x, T *alp, int n, T *p) const
115
- {
116
- S *q = knots;
117
- int K = rank, J = K - 1;
118
- int Imax = Kset(x);
119
- for (int ql = J; ql <= Imax; ++ql) {
120
- S t = q[ql];
121
- parray<S> fl = bases(t, J);
122
- int ks = fl(0), kt = fl(1), kset = ks + J;
123
- S *ft = *fl, Qh = (ql < Imax ? q[ql+1] : x) - t;
124
- for (int i = ks; i <= kset; ++i) {
125
- S Qs = 0.0; int j = i - ks + K * kt;
126
- for (int r = K; r > 0; --r) {
127
- S Bik = ft[j -= kt];
128
- Qs = (Qs + Bik) * Qh / (S)r;
129
- }
130
- for (int k = 0; k < n; ++k) p[k] += alp[n*i+k] * Qs;
131
- }
132
- }
133
- }
134
-
135
- }; // end of base_spline;
136
-
137
- #endif
1
+ #ifndef _BASIS_H_INCLUDED_
2
+ #define _BASIS_H_INCLUDED_
3
+ #include <assert.h>
4
+
5
+ template <typename P, typename T>
6
+ int deboor(int, const P&, int, const T&, P&, int&, int = 0);
7
+ template <typename P, typename T>
8
+ void deboor_cox(int, const P&, int, const T&, P&, int&, int, int = 0);
9
+
10
+ /*******************************************************************************
11
+ Bスプライン基底(節点列によるBスプライン関数計算)
12
+ *******************************************************************************/
13
+ template <typename S = double> class base_spline
14
+ {
15
+ protected:
16
+ int imax, icox, rank, jisu, shuki, maxq;
17
+ varray<S> *knots;
18
+ base_spline *Base() { return this; }
19
+ public:
20
+ // default constructor
21
+ base_spline() : knots(NULL) {}
22
+ // constructor
23
+ base_spline(int, const varray<S>&, int, int = 0, int* = NULL);
24
+ base_spline(const varray<S>&, int, int, int);
25
+ // copy constructor
26
+ base_spline(const base_spline&);
27
+ // destructor
28
+ ~base_spline() { delete knots; }
29
+ // assignment operator
30
+ base_spline& operator=(const base_spline&);
31
+ // properties
32
+ int Imax() const { return imax; }
33
+ int Icox() const { return icox; }
34
+ int Rank() const { return rank; }
35
+ int Jisu() const { return jisu; }
36
+ int Shuki()const { return shuki;}
37
+ int Maxq() const { return maxq; }
38
+ varray<S>& Knots() const { return *knots; }
39
+ int Kset(const real<S>& x) const;
40
+ real<S> x_max() const {return (*knots)[icox];}
41
+ real<S> x_min() const {return (*knots)[jisu];}
42
+ real<S> operator[] (int i) const {return (*knots)[i];}
43
+ int basic(const real<S>&, int, varray<S>&, int = 0) const;
44
+ void bibun_keisu(int, marray<S>&) const;
45
+ void sekibun_keisu(int, marray<S>&) const;
46
+ void gyoretu(marray<S>&, int, const varray<S>&, const int* = NULL) const;
47
+ marray<S> gyoretu(const Int&, const varray<S>&, const int* = NULL) const;
48
+ parray<S> basis(const real<S>&, int = 0) const;
49
+ parray<S> bases(const real<S>&, int = 0) const;
50
+ parray<S> sekibun(const real<S>&, int) const;
51
+ void print() const;
52
+ /*******************************************************************************
53
+ 線形結合係数の適用 Σa[i]*b[i]; i = kset-Kai+1,...,kset;
54
+ d: d > 0 ? 微分階数 : d == 0 ? 補間値 : 高階積分
55
+ t: データ点の座標値
56
+ alp: (微分)線形結合係数の配列
57
+ *******************************************************************************/
58
+ template <typename T> real<T> apply(const real<S>& t, const varray<T>& alp, int d = 0) const
59
+ {
60
+ if (d >= 0) {
61
+ assert(rank > d);
62
+ int k = rank - d;
63
+ varray<S> b(size_t(icox), t.atom());
64
+ int ks = basic(t, icox, b, k);
65
+ int kset = ks + k - 1;
66
+ if (ks < 0) ks = 0;
67
+ real<T> sum(T(), t.atom());
68
+ for (int i = ks; i <= kset; i++) sum += alp[i] * b[i];
69
+ return sum;
70
+ } else
71
+ return sekibun<T,real<T>,varray<T> >(t, alp, d);
72
+ }
73
+ /*******************************************************************************
74
+ 不定積分の計算
75
+ *******************************************************************************/
76
+ template <typename T> real<T> sekibun(const real<S>& x, const varray<T>& alp) const
77
+ {
78
+ const varray<S>& q = *knots;
79
+ int K = rank, J = K - 1;
80
+ int Imax = Kset(x);
81
+ real<T> sum(alp.atom());
82
+ for (int ql = J; ql <= Imax; ++ql) {
83
+ real<S> t = q[ql];
84
+ parray<S> fl = bases(t, J);
85
+ int ks = fl.offset(), kset = ks + J;
86
+ real<S> Qh = (ql < Imax ? q[ql+1] : x) - t;
87
+ for (int i = ks; i <= kset; ++i) {
88
+ real<S> Qs = fl.saylor(i - ks, Qh);
89
+ sum += alp[i] * Qs;
90
+ }
91
+ }
92
+ return sum;
93
+ }
94
+ /*******************************************************************************
95
+ 高階積分の計算
96
+ *******************************************************************************/
97
+ template <typename T, typename P = real<T>, typename Q = varray<T> >
98
+ P sekibun(const real<S>& t, const Q& alp, int Jsk) const
99
+ {
100
+ assert(Jsk < 0);
101
+ size_t A = alp.atom();
102
+ int k = rank - Jsk;
103
+ varray<S> b(size_t(k), t.atom());
104
+ const varray<S>& q = *knots;
105
+ int kset, ks = deboor(rank, q, icox, t, b, kset, k);
106
+ Q a(size_t(kset+1), A);
107
+ for (int i = 0; i <= kset; ++i) a[i] = alp[i];
108
+ while (Jsk < 0) {
109
+ P ab(T(), A);
110
+ for (int i = 0; i <= kset; ++i) {
111
+ real<S> w = (q[i+(k+Jsk)] - q[i]) / S(k+Jsk);
112
+ a[i] = ab + a[i] * w; ab = a[i];
113
+ }
114
+ Jsk++;
115
+ }
116
+ P sek(T(), A);
117
+ for (int i = ks > 0 ? ks : 0; i <= kset; ++i) sek += a[i] * b[i-ks];
118
+ return sek;
119
+ }
120
+ /*******************************************************************************
121
+ 多次元積分の計算
122
+ *******************************************************************************/
123
+ template <typename T> varray<T> sekibun(const real<S>& x, const marray<T>& clp) const
124
+ {
125
+ const varray<S>& q = *knots;
126
+ int K = rank, J = K - 1;
127
+ int Imax = Kset(x);
128
+ varray<T> p(T(), clp.cols(), clp.atom());
129
+ for (int ql = J; ql <= Imax; ++ql) {
130
+ real<S> t = q[ql];
131
+ parray<S> fl = bases(t, J);
132
+ int ks = fl.offset(), kset = ks + J;
133
+ real<S> Qh = (ql < Imax ? q[ql+1] : x) - t;
134
+ for (int i = ks; i <= kset; ++i) {
135
+ real<S> Qs = fl.saylor(i - ks, Qh);
136
+ size_t n = p.size();
137
+ for (size_t k = 0; k < n; ++k) p[k] += clp[i][k] * Qs;
138
+ }
139
+ }
140
+ return p;
141
+ }
142
+
143
+ }; // end of base_spline;
144
+
145
+ #endif
@@ -1,152 +1,188 @@
1
- #ifndef _FFT_H_INCLUDED_
2
- #define _FFT_H_INCLUDED_
3
-
4
- template <typename T> bool rft(T *, size_t, int); // 実数値高速フーリエ変換
5
- template <typename T> bool cft(T *, size_t, int); // 複素高速フーリエ変換(実数値配列引数)
6
-
7
- template <typename T = double, typename S = T> struct fft
8
- {
9
-
10
- static bool complex_forward(T *dat, int N) { return cft(dat, N << 1, 1); }
11
-
12
- static bool complex_backward(T *dat, int N) { return cft(dat, N << 1, 0); }
13
-
14
- static bool complex_inverse(T *dat, int N) { return cft(dat, N << 1, -1); }
15
-
16
- static bool complex_transform(T *dat, int N, int f) { return cft(dat, N << 1, f); }
17
-
18
- static void half_en_pack(double *data, size_t n, double *dfft)
19
- {
20
- size_t nn, i, j;
21
- double *data1 = data, *data2 = data + n;
22
-
23
- nn = n + n;
24
- data1[0] = dfft[0]; data2[0] = dfft[1];
25
- for (i = 2; i < n; i += 2) {
26
- j = nn - i;
27
- data1[i-1] = 0.5*(dfft[ j ] + dfft[ i ]);
28
- data1[ i ] = 0.5*(dfft[i+1] - dfft[j+1]);
29
- data2[i-1] = 0.5*(dfft[i+1] + dfft[j+1]);
30
- data2[ i ] = 0.5*(dfft[ j ] - dfft[ i ]);
31
- }
32
- if (i == n) {
33
- data1[i-1] = dfft[i]; data2[i-1] = dfft[i+1];
34
- }
35
- }
36
-
37
- static void complex_get(T *data, int N, int i, T *val)
38
- {
39
- i %= N;
40
- if (N/2 < i ) i -= N;
41
- if (i < -N/2) i += N;
42
- T *var = &data[(i < 0 ? i + N : i) << 1];
43
- val[0] = var[0];
44
- val[1] = var[1];
45
- }
46
-
47
- static bspline<T,S> *cfft(T *dat, int N, int j)
48
- {
49
- T *data = new T[N << 1];
50
- S *x = new S[N+1];
51
- for (int i = 0; i < N; ++i) {
52
- x[i] = i - N/2;
53
- int r = i < N/2 ? i + N/2 + N%2 : i - N/2;
54
- data[2*i] = dat[r*2];
55
- data[2*i+1] = dat[r*2+1];
56
- } x[N] = N - N/2;
57
- bspline<T,S> *wfft = make_bspline<2,T,S>(x, N, data, j, 1);
58
- delete[] x;
59
- delete[] data;
60
- return wfft;
61
- }
62
-
63
- static bool real_forward(T *dat, int N) { return rft(dat, N, 1); }
64
-
65
- static bool real_backward(T *dat, int N) { return rft(dat, N, 0); }
66
-
67
- static bool real_inverse(T *dat, int N) { return rft(dat, N, -1); }
68
-
69
- static bool real_transform(T *dat, int N, int f) { return rft(dat, N, f); }
70
-
71
- static void half_de_pack(double *dfft, size_t n, double *data)
72
- {
73
- size_t nn, i, j;
74
- double *data1 = data, *data2 = data + n;
75
-
76
- nn = n + n;
77
- dfft[0] = data1[0]; dfft[1] = data2[0];
78
- for (i = 2; i < n; i += 2) {
79
- j = nn - i;
80
- dfft[ i ] = data1[i-1] - data2[ i ];
81
- dfft[i+1] = data2[i-1] + data1[ i ];
82
- dfft[ j ] = data1[i-1] + data2[ i ];
83
- dfft[j+1] = data2[i-1] - data1[ i ];
84
- }
85
- if (i == n) {
86
- dfft[n] = data1[n-1]; dfft[n+1] = data2[n-1];
87
- }
88
- }
89
-
90
- static void real_get(T *data, int N, int i, T *val)
91
- {
92
- i %= N;
93
- if (N/2 < i ) i -= N;
94
- if (i < -N/2) i += N;
95
- int j = (i < 0 ? -i : i) << 1;
96
- T *var = &data[i == 0 ? 0 : j - 1];
97
- val[0] = var[0];
98
- if (i == 0 || j == N)
99
- val[1] = 0;
100
- else
101
- val[1] = var[1] * (i < 0 ? -1 : 1);
102
- }
103
-
104
- static void half_get(T *data1, int N, int i, T *val)
105
- {
106
- i %= N;
107
- if (N/2 < i ) i -= N;
108
- if (i < -N/2) i += N;
109
- int j = (i < 0 ? -i : i) << 1;
110
- T *data2 = data1 + N;
111
- if (i == 0) {
112
- val[0] = data1[0];
113
- val[1] = data2[0];
114
- } else if (j == N) {
115
- val[0] = data1[N-1];
116
- val[1] = data2[N-1];
117
- } else if (i < 0) {
118
- val[0] = data1[j-1] + data2[j];
119
- val[1] = data2[j-1] - data1[j];
120
- } else {
121
- val[0] = data1[j-1] - data2[j];
122
- val[1] = data2[j-1] + data1[j];
123
- }
124
- }
125
-
126
- static bspline<T,S> *rfft(T *dat, int N, int j)
127
- {
128
- T *data = new T[N << 1];
129
- S *x = new S[N+1];
130
- for (int i = 0; i < N; ++i) {
131
- x[i] = i - N/2;
132
- int r = i < N/2 ? N/2 - i : i - N/2;
133
- if (i == 0 && N%2 == 0) {
134
- data[0] = dat[2*r-1];
135
- data[1] = 0.0;
136
- } else if (i == N/2) {
137
- data[2*i] = dat[0];
138
- data[2*i+1] = 0.0;
139
- } else {
140
- data[2*i] = dat[2*r-1];
141
- data[2*i+1] = dat[2*r] * (i < N/2 ? -1 : 1);
142
- }
143
- } x[N] = N - N/2;
144
- bspline<T,S> *wfft = make_bspline<2,T,S>(x, N, data, j, 1);
145
- delete[] x;
146
- delete[] data;
147
- return wfft;
148
- }
149
-
150
- }; // end of fft;
151
-
152
- #endif
1
+ #ifndef _FFT_H_INCLUDED_
2
+ #define _FFT_H_INCLUDED_
3
+ #include "basis/marray_ext.h"
4
+ #include "basis/real_inline.h"
5
+ #include "basis/marray_class_ext.h"
6
+ #include "basis/util.h"
7
+ #include "basis/poly_array.h"
8
+ #include "basis/basis.h"
9
+ #include "basis/pspline.h"
10
+
11
+ template <typename T> bool rfft(varray<T>&, size_t, int); // 実数値高速フーリエ変換
12
+ template <typename T> bool cfft(varray<T>&, size_t, int); // 複素高速フーリエ変換(実数値配列引数)
13
+
14
+ template <typename T = double, typename S = T> struct fft
15
+ {
16
+
17
+ static bool complex_forward(varray<T>& dat) { return cfft(dat, dat.size(), 1); }
18
+
19
+ static bool complex_backward(varray<T>& dat) { return cfft(dat, dat.size(), 0); }
20
+
21
+ static bool complex_inverse(varray<T>& dat) { return cfft(dat, dat.size(), -1); }
22
+
23
+ static bool complex_transform(varray<T>& dat, int f) { return cfft(dat, dat.size(), f); }
24
+
25
+ static varray<T> half_en_pack(const varray<T>& dfft)
26
+ {
27
+ size_t nn = dfft.size(), n = nn >> 1, i, j;
28
+ varray<T> data(nn, dfft.atom());
29
+ const varray<T>& data1 = data[0], &data2 = data[n];
30
+
31
+ data1[0] = dfft[0]; data2[0] = dfft[1];
32
+ for (i = 2; i < n; i += 2) {
33
+ j = nn - i;
34
+ data1[i-1] = 0.5*(dfft[ j ] + dfft[ i ]);
35
+ data1[ i ] = 0.5*(dfft[i+1] - dfft[j+1]);
36
+ data2[i-1] = 0.5*(dfft[i+1] + dfft[j+1]);
37
+ data2[ i ] = 0.5*(dfft[ j ] - dfft[ i ]);
38
+ }
39
+ if (i == n) {
40
+ data1[i-1] = dfft[i]; data2[i-1] = dfft[i+1];
41
+ }
42
+ return data;
43
+ }
44
+
45
+ static void complex_get(const varray<T>& data, int i, varray<T>& val)
46
+ {
47
+ int nn = data.size(), N = nn >> 1;
48
+ i %= N;
49
+ if (N/2 < i ) i -= N;
50
+ if (i < -N/2) i += N;
51
+ const varray<T>& var = data[(i < 0 ? i + N : i) << 1];
52
+ val[0] = var[0];
53
+ val[1] = var[1];
54
+ }
55
+
56
+ static bspline<T,S> *cfft_spline(const varray<T>& dfft, int j)
57
+ {
58
+ int nn = dfft.size(), N = nn >> 1;
59
+ size_t A = dfft.atom();
60
+ poly_array<T> Y(Int{N, 2, int(A)});
61
+ varray<S> X(size_t(N+1), A);
62
+ const varray<T>& data = *Y;
63
+ for (int i = 0; i < N; ++i) {
64
+ X[i] = T(i - N/2);
65
+ int r = i < N/2 ? i + N/2 + N%2 : i - N/2;
66
+ data[2*i] = dfft[r*2];
67
+ data[2*i+1] = dfft[r*2+1];
68
+ } X[N] = T(N - N/2);
69
+ return new bspline<T,S>(Y, X, N+1, j, 1);
70
+ }
71
+
72
+ static bool real_forward(varray<T>& dat) { return rfft(dat, dat.size(), 1); }
73
+
74
+ static bool real_backward(varray<T>& dat) { return rfft(dat, dat.size(), 0); }
75
+
76
+ static bool real_inverse(varray<T>& dat) { return rfft(dat, dat.size(), -1); }
77
+
78
+ static bool real_transform(varray<T>& dat, int f) { return rfft(dat, dat.size(), f); }
79
+
80
+ static varray<T> half_de_pack(const varray<T>& data)
81
+ {
82
+ size_t nn = data.size(), n = nn >> 1, i, j;
83
+ varray<T> dfft(nn, data.atom());
84
+ const varray<T>& data1 = data[0], &data2 = data[n];
85
+
86
+ dfft[0] = data1[0]; dfft[1] = data2[0];
87
+ for (i = 2; i < n; i += 2) {
88
+ j = nn - i;
89
+ dfft[ i ] = data1[i-1] - data2[ i ];
90
+ dfft[i+1] = data2[i-1] + data1[ i ];
91
+ dfft[ j ] = data1[i-1] + data2[ i ];
92
+ dfft[j+1] = data2[i-1] - data1[ i ];
93
+ }
94
+ if (i == n) {
95
+ dfft[n] = data1[n-1]; dfft[n+1] = data2[n-1];
96
+ }
97
+ return dfft;
98
+ }
99
+
100
+ static void real_get(varray<T>& data, int i, varray<T>& val)
101
+ {
102
+ int N = data.size();
103
+ i %= N;
104
+ if (N/2 < i ) i -= N;
105
+ if (i < -N/2) i += N;
106
+ int j = (i < 0 ? -i : i) << 1;
107
+ const varray<T>& var = data[i == 0 ? 0 : j - 1];
108
+ val[0] = var[0];
109
+ if (i == 0 || j == N)
110
+ val[1] = T();
111
+ else
112
+ val[1] = var[1] * (i < 0 ? -1 : 1);
113
+ }
114
+
115
+ static void half_get(varray<T>& data1, int i, varray<T>& val)
116
+ {
117
+ int nn = data1.size(), N = nn >> 1;
118
+ i %= N;
119
+ if (N/2 < i ) i -= N;
120
+ if (i < -N/2) i += N;
121
+ int j = (i < 0 ? -i : i) << 1;
122
+ const varray<T>& data2 = data1[N];
123
+ if (i == 0) {
124
+ val[0] = data1[0];
125
+ val[1] = data2[0];
126
+ } else if (j == N) {
127
+ val[0] = data1[N-1];
128
+ val[1] = data2[N-1];
129
+ } else if (i < 0) {
130
+ val[0] = data1[j-1] + data2[j];
131
+ val[1] = data2[j-1] - data1[j];
132
+ } else {
133
+ val[0] = data1[j-1] - data2[j];
134
+ val[1] = data2[j-1] + data1[j];
135
+ }
136
+ }
137
+
138
+ static bspline<T,S> *rfft_spline(varray<T>& dat, int j)
139
+ {
140
+ int N = dat.size();
141
+ size_t A = dat.atom();
142
+ poly_array<T> Y(Int{N, 2, int(A)});
143
+ varray<S> X(size_t(N+1), A);
144
+ const varray<T>& data = *Y;
145
+ for (int i = 0; i < N; ++i) {
146
+ X[i] = T(i - N/2);
147
+ int r = i < N/2 ? N/2 - i : i - N/2;
148
+ if (i == 0 && N%2 == 0) {
149
+ data[0] = dat[2*r-1];
150
+ data[1] = T();
151
+ } else if (i == N/2) {
152
+ data[2*i] = dat[0];
153
+ data[2*i+1] = T();
154
+ } else {
155
+ data[2*i] = dat[2*r-1];
156
+ data[2*i+1] = dat[2*r] * T(i < N/2 ? -1 : 1);
157
+ }
158
+ } X[N] = T(N - N/2);
159
+ return new bspline<T,S>(Y, X, N+1, j, 1);
160
+ }
161
+
162
+ static varray<T> real_mul(const varray<T>& data1, const varray<T>& data2)
163
+ {
164
+ size_t N = data1.size();
165
+ size_t A = data1.atom();
166
+ varray<T> result(N, A);
167
+ for (size_t i = 0; i <= N; i += 2) {
168
+ if (i == 0) result[ i ] = data1[ i ] * data2[ i ]; else
169
+ if (i == N) result[N-1] = data1[N-1] * data2[N-1]; else
170
+ {
171
+ result[i-1] = data1[i-1]*data2[i-1] - data1[i]*data2[ i ];
172
+ result[ i ] = data1[i-1]*data2[ i ] + data1[i]*data2[i-1];
173
+ }
174
+ }
175
+ return result;
176
+ }
177
+
178
+ static varray<T> half_mul(const varray<T>& data)
179
+ {
180
+ size_t n = data.size(), N = n >> 1;
181
+ size_t A = data.atom();
182
+ varray<T> vect((T*)data, N, A);
183
+ return real_mul(vect, data[N]);
184
+ }
185
+
186
+ }; // end of fft;
187
+
188
+ #endif