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,137 @@
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
@@ -0,0 +1,152 @@
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
@@ -0,0 +1,1568 @@
1
+ #ifndef _POLY_ARRAY_5_H_INCLUDED_
2
+ #define _POLY_ARRAY_5_H_INCLUDED_
3
+ #include <stdarg.h>
4
+
5
+ template<typename T> class poly_array;
6
+ template<typename T> class poly_view;
7
+ template<typename T> class poly_array_lu;
8
+ template<typename T> class comb_array;
9
+ template<typename T> class comb_view;
10
+ template<typename T> class comp_array;
11
+ template<typename T> class comp_view;
12
+
13
+ typedef enum {Atom, Colon, Slate, Cube, Tetra, Penta, Hexa} grid_type;
14
+
15
+ template <typename T>
16
+ void poly_subst(int n, T *w)
17
+ {
18
+ for (int i = 0; i <= n; ++i) w[i] = 1;
19
+ }
20
+
21
+ template <typename T, class... Args>
22
+ void poly_subst(int n, T *w, T car, Args... cdr)
23
+ {
24
+ w[0] = car; if (n > 0) poly_subst(n-1, &w[1], cdr...);
25
+ }
26
+
27
+ /*******************************************************************************
28
+ poly<T>(N, T[N]);
29
+ [T0,...,TN]
30
+ *******************************************************************************/
31
+ template<typename T> class poly
32
+ {
33
+ template<class> friend class poly;
34
+ template<class> friend class poly_array;
35
+ template<class> friend class poly_view;
36
+ template<class> friend class poly_array_lu;
37
+ template<class> friend class comb_array;
38
+ template<class> friend class comb_view;
39
+ template<class> friend class comp_array;
40
+ template<class> friend class comp_view;
41
+
42
+ int N, *cp; T *w; // data fields
43
+
44
+ public:
45
+ poly(): cp(NULL), w(NULL) {}
46
+ // constructor
47
+ // poly<T>(T*, N); alias of T*
48
+ poly(T *a, int n = 1) : N(n), cp(NULL), w(a) {} // [T0,...,Tn]
49
+ // poly<T>(N, T0, ...);
50
+ template <class... Args>
51
+ poly(int n, const T car, const Args... cdr) : N(n), cp(new int(1)), w(new T[n+1])
52
+ {
53
+ w[0] = car; if (n > 0) poly_subst(n-1, &w[1], cdr...);
54
+ }
55
+ poly(int n, const T *s) : N(n), cp(new int(1)), w(new T[n+1])
56
+ {
57
+ memcpy(w, s, (N + 1) * sizeof(T));
58
+ }
59
+ poly(int n, const T *s, T t) : N(n), cp(new int(1)), w(new T[n+1])
60
+ {
61
+ memcpy(w, s, N * sizeof(T)); w[N] = t;
62
+ }
63
+ // copy construtor
64
+ template <class S>
65
+ poly(const poly<S>& p) : N(p.N), cp(new int(1)), w(new T[p.N+1])
66
+ {
67
+ for (int i = 0; i <= N; ++i) w[i] = p.w[i];
68
+ }
69
+ poly(const poly& p) : N(p.N), cp(new int(1)), w(new T[p.N+1])
70
+ {
71
+ for (int i = 0; i <= N; ++i) w[i] = p.w[i];
72
+ }
73
+ // destructor
74
+ ~poly() { if (cp && --*cp == 0) { delete cp; delete[] w; }}
75
+ // substituton operator
76
+ poly& operator=(const poly& p)
77
+ {
78
+ if (this != &p)
79
+ {
80
+ if (cp && --*cp == 0) { delete cp; delete[] w; }
81
+ N = p.N; cp = new int(1); w = new T[p.N+1];
82
+ for (int i = 0; i <= N; ++i) w[i] = p.w[i];
83
+ }
84
+ return *this;
85
+ }
86
+ // substitute grid size
87
+ poly& operator=(const T *s)
88
+ {
89
+ memcpy(w, s, N * sizeof(T));
90
+ return *this;
91
+ }
92
+ // substitute unit size
93
+ poly& operator=(T t)
94
+ {
95
+ w[N] = t;
96
+ return *this;
97
+ }
98
+ poly operator * (const poly& p) const
99
+ {
100
+ assert(N == p.N);
101
+ T result[N];
102
+ for (int i=0;i<N;++i) result[i] = w[i] * p.w[i];
103
+ return poly(N, result, w[N]);
104
+ }
105
+ poly operator / (const poly& p) const
106
+ {
107
+ assert(N == p.N);
108
+ T result[N];
109
+ for (int i=0;i<N;++i) result[i] = w[i] / p.w[i];
110
+ return poly(N, result, w[N]);
111
+ }
112
+ poly operator + (const poly& p) const
113
+ {
114
+ assert(N == p.N);
115
+ T result[N];
116
+ for (int i=0;i<N;++i) result[i] = w[i] + p.w[i];
117
+ return poly(N, result, w[N]);
118
+ }
119
+ poly operator - (const poly& p) const
120
+ {
121
+ assert(N == p.N);
122
+ T result[N];
123
+ for (int i=0;i<N;++i) result[i] = w[i] - p.w[i];
124
+ return poly(N, result, w[N]);
125
+ }
126
+ poly& operator *= (const poly& p)
127
+ {
128
+ assert(N == p.N);
129
+ for (int i=0;i<N;++i) w[i] *= p.w[i];
130
+ return *this;
131
+ }
132
+ poly& operator /= (const poly& p)
133
+ {
134
+ assert(N == p.N);
135
+ for (int i=0;i<N;++i) w[i] /= p.w[i];
136
+ return *this;
137
+ }
138
+ poly& operator += (const poly& p)
139
+ {
140
+ assert(N == p.N);
141
+ for (int i=0;i<N;++i) w[i] += p.w[i];
142
+ return *this;
143
+ }
144
+ poly& operator -= (const poly& p)
145
+ {
146
+ assert(N == p.N);
147
+ for (int i=0;i<N;++i) w[i] -= p.w[i];
148
+ return *this;
149
+ }
150
+ poly& operator %= (const poly& p)
151
+ {
152
+ assert(N == p.N);
153
+ for (int i=0;i<N;++i) w[i] %= p.w[i];
154
+ return *this;
155
+ }
156
+ poly operator - () const
157
+ {
158
+ T s[N];
159
+ for (int i=0;i<N;++i) s[i] = - w[i];
160
+ return poly(N, s, w[N]);
161
+ }
162
+ poly operator * (T a) const
163
+ {
164
+ T s[N];
165
+ for (int i=0;i<N;++i) s[i] = w[i] * a;
166
+ return poly(N, s, w[N]);
167
+ }
168
+ poly operator / (T a) const
169
+ {
170
+ T s[N];
171
+ for (int i=0;i<N;++i) s[i] = w[i] / a;
172
+ return poly(N, s, w[N]);
173
+ }
174
+ poly operator + (T a) const
175
+ {
176
+ T s[N];
177
+ for (int i=0;i<N;++i) s[i] = w[i] + a;
178
+ return poly(N, s, w[N]);
179
+ }
180
+ poly operator - (T a) const
181
+ {
182
+ T s[N];
183
+ for (int i=0;i<N;++i) s[i] = w[i] - a;
184
+ return poly(N, s, w[N]);
185
+ }
186
+ poly operator % (int a) const
187
+ {
188
+ T s[N];
189
+ for (int i=0;i<N;++i) s[i] = w[i] % a;
190
+ return poly(N, s, w[N]);
191
+ }
192
+ poly& operator *= (T a)
193
+ {
194
+ for(int i=0;i<N;i++) w[i] *= a;
195
+ return *this;
196
+ }
197
+ poly& operator /= (T a)
198
+ {
199
+ for(int i=0;i<N;i++) w[i] /= a;
200
+ return *this;
201
+ }
202
+ poly& operator += (T a)
203
+ {
204
+ for(int i=0;i<N;i++) w[i] += a;
205
+ return *this;
206
+ }
207
+ poly& operator -= (T a)
208
+ {
209
+ for(int i=0;i<N;i++) w[i] -= a;
210
+ return *this;
211
+ }
212
+ poly& operator %= (T a)
213
+ {
214
+ for(int i=0;i<N;i++) w[i] %= a;
215
+ return *this;
216
+ }
217
+ bool operator == (const poly& p) const
218
+ {
219
+ assert(N == p.N);
220
+ int i; for(i=0;i<N;++i) if(w[i] != p.w[i]) break;
221
+ return i == N && w[N] == p.w[N];
222
+ }
223
+ bool operator != (const poly& p) const
224
+ {
225
+ assert(N == p.N);
226
+ int i; for(i=0;i<N;i++) if(w[i] != p.w[i]) break;
227
+ return i != N || w[N] != p.w[N];
228
+ }
229
+ bool operator > (const poly& p) const
230
+ {
231
+ assert(N == p.N);
232
+ int i; for(i=0;i<N;++i) if(w[i] <= p.w[i]) break;
233
+ return i == N && w[N] == p.w[N];
234
+ }
235
+ bool operator >= (const poly& p) const
236
+ {
237
+ assert(N == p.N);
238
+ int i; for(i=0;i<N;++i) if(w[i] < p.w[i]) break;
239
+ return i == N && w[N] == p.w[N];
240
+ }
241
+ bool operator < (const poly& p) const
242
+ {
243
+ assert(N == p.N);
244
+ int i; for(i=0;i<N;i++) if(w[i] >= p.w[i]) break;
245
+ return i == N && w[N] == p.w[N];
246
+ }
247
+ bool operator <= (const poly& p) const
248
+ {
249
+ assert(N == p.N);
250
+ int i; for(i=0;i<N;i++) if(w[i] > p.w[i]) break;
251
+ return i == N && w[N] == p.w[N];
252
+ }
253
+ bool operator == (int a) const
254
+ {
255
+ int i;
256
+ for (i = 0; i < N; ++i) if (w[i] != a) break;
257
+ return i == N;
258
+ }
259
+ bool operator != (int a) const
260
+ {
261
+ int i;
262
+ for (i = 0; i < N; ++i) if (w[i] != a) break;
263
+ return i != N;
264
+ }
265
+ bool operator < (int a) const
266
+ {
267
+ int i;
268
+ for (i = 0; i < N; ++i) if (w[i] >= a) break;
269
+ return i == N;
270
+ }
271
+ bool operator >= (int a) const
272
+ {
273
+ int i;
274
+ for (i = 0; i < N; ++i) if (w[i] < a) break;
275
+ return i == N;
276
+ }
277
+ bool operator > (int a) const
278
+ {
279
+ int i;
280
+ for (i = 0; i < N; ++i) if (w[i] <= a) break;
281
+ return i == N;
282
+ }
283
+ bool operator <= (int a) const
284
+ {
285
+ int i;
286
+ for (i = 0; i < N; ++i) if (w[i] > a) break;
287
+ return i == N;
288
+ }
289
+ // member function
290
+ int length() const {return N+1;}
291
+ // Π w[i] : i = n,...,N
292
+ T data_size(int n = 0) const
293
+ {
294
+ assert(n <= N);
295
+ T z = 1;
296
+ for(int i = N; i > n; --i) z *= w[i-1];
297
+ return z * w[N];
298
+ }
299
+ // (Σ com[i] : i = n,...,N-1) * unit_size
300
+ T comb_size(int n = 0) const
301
+ {
302
+ assert(n <= N);
303
+ int z = (n == N ? 1 : 0);
304
+ for(int i = N; i > n; --i) z += w[i-1];
305
+ return z * w[N];
306
+ }
307
+ T cast_size(int n, int m = 0) const
308
+ {
309
+ assert(0 < N && n <= N && m <= n);
310
+ int z = 0;
311
+ for(int i = m; i < n; ++i) z += w[i];
312
+ return z * w[N];
313
+ }
314
+ // Π w[i] : i = 0,...,N-1
315
+ T grid_size() const
316
+ {
317
+ T z = 1;
318
+ for (int k = 0; k < N; ++k) z *= w[k];
319
+ return z;
320
+ }
321
+ // Σ w[i] : i = 0,...,N-1
322
+ T band_size() const
323
+ {
324
+ T z = 0;
325
+ for (int k = 0; k < N; ++k) z += w[k];
326
+ return z;
327
+ }
328
+ int grid() const {return N;}
329
+ // w[N]
330
+ T unit_size() const { return w[N]; }
331
+ // pointer of w
332
+ operator T* () const { return w; }
333
+ // calculate Atom Position
334
+ T operator && (const poly& p) const
335
+ {
336
+ int M = p.N;
337
+ assert(N >= M);
338
+ T sum = p.w[M];
339
+ T sek = w[N];
340
+ for (int i = N-1; i >= 0; --i) {
341
+ if (i < M)
342
+ sum += sek * p.w[i];
343
+ sek *= w[i];
344
+ }
345
+ return sum;
346
+ }
347
+ bool is_variable() const
348
+ {
349
+ int N = this->grid(); T n = this->data_size();
350
+ return N == 0 && n == 1;
351
+ }
352
+ // dimension of grid
353
+ bool is_atom() const { return N == Atom; }
354
+ bool is_colon() const { return N == Colon; }
355
+ bool is_slate() const { return N == Slate; }
356
+ bool is_cube() const { return N == Cube; }
357
+ // type conversion operator
358
+ // Referrece of element.
359
+ T operator[] (int i) const { return w[i]; }
360
+ // operators
361
+ poly operator<<(int i) const { return poly(N-i, &w[i]); }
362
+ poly operator>>(int i) const { return poly(N-i, w, data_size(N-i)); }
363
+ poly operator+() { return poly(Colon, grid_size(), unit_size()); }
364
+ char *to_s() const
365
+ {
366
+ char buf[512];
367
+ char *c = buf;
368
+ sprintf(c++, "<");
369
+ if (N > 0) {
370
+ sprintf(c++, "{");
371
+ for (int i = 0; i < N; ++i) {
372
+ sprintg(c, w[i]); while(*c)++c;
373
+ if (i == N-1) sprintf(c++, "}");
374
+ sprintf(c++, ",");
375
+ }
376
+ }
377
+ sprintg(c, w[N]); while(*c)++c;
378
+ sprintf(c++, ">");
379
+ int n = c - buf;
380
+ char *result = new char[n + 1];
381
+ strcpy(result, buf);
382
+ return result;
383
+ }
384
+ void print(const char *end = NULL) const {
385
+ char *s = this->to_s();
386
+ char f[32] = {"%s"};
387
+ char *c = f; while(*c)++c;
388
+ if (end) sprintf(c, "%s", end);
389
+ fprintf(stdout, f, s);
390
+ delete[] s;
391
+ }
392
+ // end of poly;
393
+ };
394
+
395
+ // poly type alias
396
+ typedef poly<int> Int ;
397
+ typedef poly<size_t> Size_t;
398
+ typedef poly<double> Double;
399
+
400
+ // Modular operation : Unit No. -> Poly Grid.
401
+ template<class T>
402
+ poly<T> operator % (T a, const poly<T>& q)
403
+ {
404
+ int N = q.grid();
405
+ T p[N];
406
+ T sho = a;
407
+ for (int i = N-1; i >= 0; --i) {
408
+ T qh = q[i];
409
+ p[i] = sho % qh;
410
+ sho /= qh;
411
+ }
412
+ return poly<T>(N, p, 0);
413
+ }
414
+
415
+ /*******************************************************************************
416
+ This section define poly_array<T>: [N, size[N], type, data[size]]
417
+ *******************************************************************************/
418
+ template<typename T = double> class poly_array : public Int
419
+ {
420
+ template<class> friend class poly_view;
421
+ template<class> friend class poly_array_lu;
422
+
423
+ const T *data; // data fields
424
+
425
+ void init_data(const T *dat)
426
+ {
427
+ size_t z = this->data_size();
428
+ T *dt = new T[z];
429
+ memcpy(dt, dat, z * sizeof(T));
430
+ data = dt;
431
+ }
432
+
433
+ public:
434
+ // Atom constructor
435
+ poly_array(const T *dat) : Int(Atom, 1), data(new T)
436
+ {
437
+ T *dt = const_cast<T*>(data);
438
+ *dt = *dat;
439
+ }
440
+ poly_array(const T *dat, int s) : Int(Atom, s), data(new T[s])
441
+ {
442
+ if (s == 0) throw "illegal construct, poly_array(T*,int)";
443
+ T *dt = const_cast<T*>(data);
444
+ memcpy(dt, dat, s * sizeof(T));
445
+ }
446
+ // Default constructor
447
+ poly_array() : data(NULL) {}
448
+ // General constructor
449
+ template <class... Args>
450
+ poly_array(const T *dat, int n, Args... cdr) : Int(n, cdr...) { init_data(dat); }
451
+ poly_array(const T *dat, int n, int *s) : Int(n, s) { init_data(dat); }
452
+ poly_array(const T *dat, int n, int *s, int t) : Int(n, s, t) { init_data(dat); }
453
+ poly_array(const T *dat, const Int& s) : Int(s) { init_data(dat); }
454
+ poly_array(int n, const poly_array& v) : Int(Int(v).N-1, Int(v).w+1)
455
+ {
456
+ size_t z = this->data_size();
457
+ T *dt = new T[z];
458
+ memcpy(dt, &v.data[n * z], z * sizeof(T));
459
+ data = dt;
460
+ }
461
+ // copy constructor
462
+ poly_array(const poly_array& pa) : Int(pa) { init_data(pa.data); }
463
+ // destructor
464
+ ~poly_array() { delete data; }
465
+ // substitution operator
466
+ poly_array& operator=(const poly_array& pa)
467
+ {
468
+ if (this != &pa) {
469
+ delete[] data;
470
+ Int::operator=(pa);
471
+ init_data(pa.data);
472
+ }
473
+ return *this;
474
+ }
475
+ poly_array& operator=(T a)
476
+ {
477
+ size_t n = this->data_size();
478
+ for (size_t i = 0; i < n; ++i)
479
+ data[i] = a;
480
+ return *this;
481
+ }
482
+ // type conversion operator
483
+ operator T* () const {return const_cast<T*>(data);}
484
+ // member function
485
+ int rows() { return Int(*this)[0]; }
486
+ int cols() { return Int(*this)[1]; }
487
+ T operator[](int pos) const
488
+ {
489
+ return data[pos];
490
+ }
491
+ int operator()(int i) const
492
+ {
493
+ return Int::operator[](i);
494
+ }
495
+ poly_view<T> operator[](const Int& p) const
496
+ {
497
+ const Int& t = *this;
498
+ int pos = t && p, N = t.N, M = p.N;
499
+ if (pos >= t.data_size())
500
+ throw "out of range, poly_array[Int]";
501
+ return poly_view<T>(&data[pos], N-M, t.w + M);
502
+ }
503
+ T operator * () const { return *data; }
504
+
505
+ poly_array operator+(const poly_array& pa) const
506
+ {
507
+ size_t n = *this; const Int& s = *this;
508
+ size_t m = pa;
509
+ if (n != m) throw "mismatch argument, poly_array + ";
510
+ T result[n];
511
+ for (size_t i = 0; i < n; ++i) result[i] = data[i] + pa.data[i];
512
+ return poly_array(result, s);
513
+ }
514
+ poly_array operator-(const poly_array& pa) const
515
+ {
516
+ size_t n = *this; const Int& s = *this;
517
+ size_t m = pa;
518
+ if (n != m) throw "mismatch argument, poly_array - ";
519
+ T result[n];
520
+ for (size_t i = 0; i < n; ++i) result[i] = data[i] - pa.data[i];
521
+ return poly_array(result, s);
522
+ }
523
+ poly_array operator%(T a) const
524
+ {
525
+ size_t n = *this; const Int& s = *this;
526
+ T result[n];
527
+ for (size_t i = 0; i < n; ++i) result[i] = data[i] % a;
528
+ return poly_array(result, s);
529
+ }
530
+ char *to_s() const
531
+ {
532
+ char buf[1024];
533
+ char *c = buf;
534
+ const Int& p = *this;
535
+ char *s = p.to_s();
536
+ sprintf(c, "{%s,", s); while(*c)++c;
537
+ delete[] s;
538
+ poly_to_s<T>(c, p.N, p.w, data);
539
+ sprintf(c++, "}");
540
+ int n = c - buf;
541
+ c = new char[n + 1];
542
+ strcpy(c, buf);
543
+ return c;
544
+ }
545
+ void print(const char *end = NULL) const {
546
+ char *s = this->to_s();
547
+ char f[32] = {"%s"};
548
+ char *c = f; while(*c)++c;
549
+ if (end) sprintf(c, "%s", end);
550
+ fprintf(stdout, f, s);
551
+ delete[] s;
552
+ }
553
+ // end poly_array
554
+ };
555
+
556
+ template<class L, class Op, class R>
557
+ class express
558
+ {
559
+ const L& l_; const R& r_;
560
+ public:
561
+ express(const L& l, const R& r) : l_(l), r_(r) {}
562
+ double operator[](int s) const { return Op::apply(l_[s], r_[s]); }
563
+ };
564
+
565
+ template<class L, class Op>
566
+ class express<L,Op,double>
567
+ {
568
+ const L& l_; const double& r_;
569
+ public:
570
+ express(const L& l, const double& r) : l_(l), r_(r) {}
571
+ double operator[](int s) const { return Op::apply(l_[s], r_); }
572
+ };
573
+
574
+ template<class Op, class R>
575
+ class unary
576
+ {
577
+ const R& r_;
578
+ public:
579
+ unary(const R& r) : r_(r) {}
580
+ double operator[](int s) const { return Op::apply(r_[s]); }
581
+ };
582
+
583
+ struct add { static double apply(double l, double r) { return l + r; } };
584
+ struct sub { static double apply(double l, double r) { return l - r; } };
585
+ struct mul { static double apply(double l, double r) { return l * r; } };
586
+ struct dvd { static double apply(double l, double r) { return l / r; } };
587
+ struct absolute { static double apply(double c) {return c < 0 ? -c : c;}};
588
+ struct minus { static double apply(double c) { return -c; } };
589
+
590
+ template <class R>
591
+ unary<absolute, R> abs(const R& rh)
592
+ {
593
+ return unary<absolute, R>(rh);
594
+ }
595
+
596
+ template<typename T> void swap(poly_view<T>&, poly_view<T>&);
597
+ /*******************************************************************************
598
+ This section define poly_view
599
+ *******************************************************************************/
600
+ template<typename T = double> class poly_view : public Int
601
+ {
602
+ template<class> friend class poly_view;
603
+ template<class> friend class poly_array_lu;
604
+
605
+ const T *data; int *cp;
606
+
607
+ public:
608
+ poly_view() : data(NULL), cp(NULL) {}
609
+ // Atom constructor
610
+ poly_view(const T *dat) : Int(Atom, 1), data(dat), cp(NULL) {}
611
+ poly_view(const T *dat, int n) : Int(Atom, n), data(dat), cp(NULL) {}
612
+ // General constructor
613
+ poly_view(const poly_array<T>& pa) : Int(pa), data(pa.data), cp(NULL) {}
614
+ template <class... Args>
615
+ poly_view(const T *dat, int n, Args... cdr) : Int(n, cdr...), data(dat), cp(NULL) {}
616
+ poly_view(const T *dat, int n, int *s) : Int(n, s), data(dat), cp(NULL) {}
617
+ poly_view(const T *dat, int n, int *s, int t) : Int(n, s, t), data(dat), cp(NULL) {}
618
+ poly_view(const T *dat, const Int& s) : Int(s), data(dat), cp(NULL) {}
619
+ poly_view(int n, const poly_view<T>& v) : Int(Int(v).N-1, Int(v).w+1)
620
+ {
621
+ int s = this->data_size();
622
+ data = &v.data[n * s]; cp = NULL;
623
+ }
624
+ // copy constructor
625
+ poly_view(const poly_view& pv) : Int(pv), data(pv.data), cp(pv.cp) { cp && ++*cp; }
626
+ // destructor
627
+ ~poly_view() { if (cp && --*cp == 0) { delete[] data; delete cp; }}
628
+ // substitution operator
629
+ poly_view& operator=(const poly_view& pv)
630
+ {
631
+ if (this != &pv)
632
+ {
633
+ int s_size = pv.data_size();
634
+ if (data == NULL) {
635
+ Int::operator=(pv);
636
+ data = new T[s_size];
637
+ cp = new int(1);
638
+ }
639
+ int d_size = this->data_size();
640
+ if ( Int::N > Atom && d_size > s_size )
641
+ {
642
+ int w[4] = {0}, &i = w[0], &j = w[2];
643
+ int c = (*this)(0), n = pv(0), k(c - n), m((k + 1) / 2), o(k - m);
644
+ Int L(&i), J(&j);
645
+ for (i=m-1,k=c-m;i>=0;--i) { j=i+k; (*this)[J] = pv[L]; }
646
+ for (i=n-1,k=o; i>=0;--i) { j=i+k; (*this)[J] = pv[L]; }
647
+ for (i=o-1,k=n; i>=0;--i) { j=i+k; (*this)[L] = (*this)[J]; }
648
+ }
649
+ else if (d_size == s_size && data != pv.data) {
650
+ T *dat = const_cast<T*>(data);
651
+ memcpy(dat, pv.data, d_size * sizeof(T));
652
+ }
653
+ else if (d_size < s_size)
654
+ throw "data size is mismatch, poly_view = ";
655
+ }
656
+ return *this;
657
+ }
658
+ poly_view& operator=(T a)
659
+ {
660
+ size_t n = this->data_size();
661
+ assert(n > 0);
662
+ T *dat = const_cast<T*>(data);
663
+ for (size_t i = 0; i < n; ++i) dat[i] = a;
664
+ return *this;
665
+ }
666
+ template<class E>
667
+ poly_view& operator=(const E& e)
668
+ {
669
+ int n = this->data_size();
670
+ assert(n > 0);
671
+ T *dat = const_cast<T*>(data);
672
+ for (int i = 0; i < n; ++i) dat[i] = e[i];
673
+ return *this;
674
+ }
675
+ // type conversion operator
676
+ operator T* () {return const_cast<T*>(data);}
677
+ // member function
678
+ int rows() {const Int& p = *this; return p[0];}
679
+ int cols() {const Int& p = *this; return p[1];}
680
+ // operators
681
+ T operator [] (int pos) const
682
+ {
683
+ return data[pos];
684
+ }
685
+ int operator () (int i) const
686
+ {
687
+ return Int(*this)[i];
688
+ }
689
+ poly_view operator [] (const Int& p) const
690
+ {
691
+ const Int& t = *this;
692
+ int pos = t && p, N = t.N, M = p.N;
693
+ if (pos >= t.data_size())
694
+ throw "out of range, poly_array[Int]";
695
+ return poly_view(&data[t && p], N-M, t.w + M);
696
+ }
697
+ T operator * () const { return *data; }
698
+ template<class R> express<poly_view, add, R> operator+(const R& pv) const
699
+ {
700
+ return express<poly_view, add, R>(*this, pv);
701
+ }
702
+ template<class R> express<poly_view, sub, R> operator-(const R& pv) const
703
+ {
704
+ return express<poly_view, sub, R>(*this, pv);
705
+ }
706
+ template<class R> express<poly_view, mul, R> operator*(const R& pv) const
707
+ {
708
+ return express<poly_view, mul, R>(*this, pv);
709
+ }
710
+ template<class R> express<poly_view, dvd, R> operator/(const R& pv) const
711
+ {
712
+ return express<poly_view, dvd, R>(*this, pv);
713
+ }
714
+ unary<minus, poly_view> operator-() const
715
+ {
716
+ return unary<minus,poly_view>(*this);
717
+ }
718
+ poly_view& operator+=(const poly_view& pv)
719
+ {
720
+ size_t n = *this;
721
+ for (size_t i = 0; i < n; ++i) data[i] += pv.data[i];
722
+ return *this;
723
+ }
724
+ template<class E> poly_view& operator+=(const E& e)
725
+ {
726
+ int n = this->data_size();
727
+ T *dat = const_cast<T*>(data);
728
+ for (int i = 0; i < n; ++i)
729
+ dat[i] += e[i];
730
+ return *this;
731
+ }
732
+ poly_view& operator-=(const poly_view& pv)
733
+ {
734
+ size_t n = *this;
735
+ for (size_t i = 0; i < n; ++i) data[i] -= pv.data[i];
736
+ return *this;
737
+ }
738
+ template<class E> poly_view& operator-=(const E& e)
739
+ {
740
+ int n = this->data_size();
741
+ T *dat = const_cast<T*>(data);
742
+ for (int i = 0; i < n; ++i)
743
+ dat[i] -= e[i];
744
+ return *this;
745
+ }
746
+ poly_view& operator*=(const poly_view& pv)
747
+ {
748
+ size_t n = this->data_size();
749
+ for (size_t i = 0; i < n; ++i) data[i] *= pv.data[i];
750
+ return *this;
751
+ }
752
+ template<class E> poly_view& operator*=(const E& e)
753
+ {
754
+ int n = this->data_size();
755
+ for (int i = 0; i < n; ++i)
756
+ data[i] *= e[i];
757
+ return *this;
758
+ }
759
+ poly_view& operator/=(const poly_view& pv)
760
+ {
761
+ size_t n = *this;
762
+ for (size_t i = 0; i < n; ++i) data[i] /= pv.data[i];
763
+ return *this;
764
+ }
765
+ template<class E> poly_view& operator/=(const E& e)
766
+ {
767
+ int n = this->data_size();
768
+ for (int i = 0; i < n; ++i)
769
+ data[i] /= e[i];
770
+ return *this;
771
+ }
772
+ bool operator==(const poly_view& pv)
773
+ {
774
+ size_t i, n = this->data_size();
775
+ for (i = 0; i < n; ++i) { if (data[i] != pv.data[i]) break; }
776
+ return i == n;
777
+ }
778
+ bool operator!=(const poly_view& pv)
779
+ {
780
+ size_t i, n = this->data_size();
781
+ for (i = 0; i < n; ++i) { if (data[i] != pv.data[i]) break; }
782
+ return i != n;
783
+ }
784
+ bool operator==(T a)
785
+ {
786
+ size_t i, n = this->data_size();
787
+ for (i = 0; i < n; ++i) { if (data[i] != a) break; }
788
+ return i == n;
789
+ }
790
+ bool operator!=(T a)
791
+ {
792
+ size_t i, n = this->data_size();
793
+ for (i = 0; i < n; ++i) { if (data[i] != a) break; }
794
+ return i != n;
795
+ }
796
+ bool operator<(const poly_view& pv)
797
+ {
798
+ size_t i, n = this->data_size();
799
+ for (i = 0; i < n; ++i) { if (data[i] >= pv.data[i]) break; }
800
+ return i == n;
801
+ }
802
+ bool operator>(const poly_view& pv)
803
+ {
804
+ size_t i, n = this->data_size();
805
+ for (i = 0; i < n; ++i) { if (data[i] <= pv.data[i]) break; }
806
+ return i == n;
807
+ }
808
+ bool operator<=(const poly_view& pv)
809
+ {
810
+ size_t i, n = this->data_size();
811
+ for (i = 0; i < n; ++i) { if (data[i] > pv.data[i]) break; }
812
+ return i == n;
813
+ }
814
+ bool operator>=(const poly_view& pv)
815
+ {
816
+ size_t i, n = this->data_size();
817
+ for (i = 0; i < n; ++i) { if (data[i] < pv.data[i]) break; }
818
+ return i == n;
819
+ }
820
+ bool operator<(T a)
821
+ {
822
+ size_t i, n = this->data_size();
823
+ for (i = 0; i < n; ++i) { if (data[i] >= a) break; }
824
+ return i == n;
825
+ }
826
+ bool operator>(T a)
827
+ {
828
+ size_t i, n = this->data_size();
829
+ for (i = 0; i < n; ++i) { if (data[i] <= a) break; }
830
+ return i == n;
831
+ }
832
+ bool operator<=(T a)
833
+ {
834
+ size_t i, n = this->data_size();
835
+ for (i = 0; i < n; ++i) { if (data[i] > a) break; }
836
+ return i == n;
837
+ }
838
+ bool operator>=(T a)
839
+ {
840
+ size_t i, n = this->data_size();
841
+ for (i = 0; i < n; ++i) { if (data[i] < a) break; }
842
+ return i == n;
843
+ }
844
+ char *to_s() const
845
+ {
846
+ char buf[1024];
847
+ char *c = buf;
848
+ const Int& p = *this;
849
+ char *s = p.to_s();
850
+ sprintf(c, "{%s,", s); while(*c)++c;
851
+ sprintf(c++, "@");
852
+ delete[] s;
853
+ poly_to_s<T>(c, p.N, p.w, data);
854
+ sprintf(c++, "}");
855
+ int n = c - buf;
856
+ c = new char[n + 1];
857
+ strcpy(c, buf);
858
+ return c;
859
+ }
860
+ void print(const char *end = NULL) const {
861
+ char *s = this->to_s();
862
+ char f[32] = {"%s"};
863
+ char *c = f; while(*c)++c;
864
+ if (end) sprintf(c, "%s", end);
865
+ fprintf(stdout, f, s);
866
+ delete[] s;
867
+ }
868
+ // end of poly_view;
869
+ };
870
+
871
+ template<typename T> void swap(poly_view<T>& p, poly_view<T>& q)
872
+ {
873
+ size_t n = p.data_size(); T *pd = p;
874
+ size_t m = q.data_size(); T *qd = q;
875
+ if (n != m) throw "size mismatch, poly_view.swap";
876
+ for (size_t i = 0; i < n; ++i) {
877
+ T w = pd[i]; pd[i] = qd[i]; qd[i] = w;
878
+ }
879
+ }
880
+ /*******************************************************************************
881
+ Matrix operation
882
+ *******************************************************************************/
883
+ template <class T>
884
+ void plu_decomp(poly_view<T>& A, int *p, int &signum)
885
+ {
886
+ if (!A.is_slate())
887
+ throw "not Slate object in plu_decomp";
888
+
889
+ int u[8]; for (int i = 0; i < 8; ++i) u[i] = 0;
890
+ int &i = u[0], &j = u[2], &k = u[4], &pivot = u[6];
891
+ Int L(&i), J(&j), K(&k), P(&pivot);
892
+ int N = A.rows(), n = A.unit_size();
893
+ T v[n], w[n];
894
+ poly_view<T> ajj(v, n), aij(w, n);
895
+
896
+ signum = 1; for (i=0;i<N;++i) p[i] = i;
897
+
898
+ for (j=0;j<N-1;++j)
899
+ {
900
+ ajj = abs(A[J][J]);
901
+ pivot = j;
902
+ for (i=j+1;i<N;++i)
903
+ {
904
+ aij = abs(A[L][J]);
905
+ if (aij > ajj)
906
+ {
907
+ ajj = aij;
908
+ pivot = i;
909
+ }
910
+ }
911
+ if (pivot != j)
912
+ {
913
+ auto a = A[J];
914
+ auto b = A[P];
915
+ swap(a, b);
916
+ int q = p[j]; p[j] = p[pivot]; p[pivot] = q;
917
+ signum = -signum;
918
+ }
919
+ if ((ajj = A[J][J]) != 0.0)
920
+ for (i=j+1;i<N;++i)
921
+ {
922
+ auto au = A[L];
923
+ auto av = A[J];
924
+ aij = au[J] / ajj;
925
+ au[J] = aij;
926
+ for (k=j+1;k<N;++k) {
927
+ au[K] -= aij * av[K];
928
+ }
929
+ }
930
+ else throw "plu_decomp division by zero";
931
+ }
932
+ }
933
+
934
+ template <class T, class S>
935
+ void plu_subst(poly_view<T>& LU, int *p, poly_view<S>& b, poly_view<S>& x)
936
+ {
937
+ int N = LU.rows();
938
+ int w[6] = {0}; int &i = w[0], &j = w[2], &k = w[4];
939
+ Int L(&i), J(&j), P(&k);
940
+
941
+ if (!(b.is_colon() || x.is_colon()))
942
+ throw "not Colon object in plu_subst";
943
+ for (i=0;i<N;++i)
944
+ {
945
+ k = p[i]; x[L] = b[P];
946
+ }
947
+ for (i=1;i<N;++i)
948
+ {
949
+ auto sum = x[L];
950
+ auto lu = LU[L];
951
+ for (j=0;j<i;++j) { sum -= x[J] * lu[J]; }
952
+ x[L] = sum;
953
+ }
954
+ for (i=N-1;i>=0;--i)
955
+ {
956
+ auto sum = x[L];
957
+ auto lu = LU[L];
958
+ for (j=N-1;j>i;--j) { sum -= x[J] * lu[J]; }
959
+ x[L] = sum / lu[L];
960
+ }
961
+ }
962
+ /*******************************************************************************
963
+ This section define poly_array_lu
964
+ *******************************************************************************/
965
+ template <typename T> class poly_array_lu : public poly_view<T>
966
+ {
967
+
968
+ int s, *sign; // data fields
969
+
970
+ public:
971
+ // constructor
972
+ poly_array_lu(const poly_array<T>& m) : poly_view<T>(m)
973
+ {
974
+ size_t r = poly_view<T>::rows();
975
+ sign = new int[r];
976
+ plu_decomp<T>(*this, sign, s);
977
+ }
978
+ ~poly_array_lu() {delete sign;}
979
+ template <typename S> poly_array<S>& solve(poly_array<S>& v)
980
+ {
981
+ poly_array<S> *result = new poly_array<S>(v.type.N, v.type.size);
982
+ plu_subst<T,S>(*this, sign, v, *result);
983
+ return *result;
984
+ }
985
+ poly_array<T> invert()
986
+ {
987
+ size_t r = poly_view<T>::rows();
988
+ size_t c = poly_view<T>::cols();
989
+ size_t t = poly_view<T>::unit_size();
990
+ size_t s = r * c * t;
991
+ T y[s], x[s];
992
+ for (size_t i = 0; i < r; ++i)
993
+ for (size_t j = 0; j < c; ++j)
994
+ for (size_t k = 0; k < t; ++k)
995
+ x[(i*c+j)*t+k] = (i == j ? 1 : 0);
996
+ Int rct(Slate, r, c, t);
997
+ Int ct(Colon, c, t);
998
+ for (size_t i = 0; i < r; ++i) {
999
+ poly_view<T> v(&y[i*c*t], ct), w(&x[i*c*t], ct);
1000
+ plu_subst<T,T>(*this, sign, w, v);
1001
+ }
1002
+ return poly_array<T>(y, rct);
1003
+ }
1004
+ poly_array<T> det()
1005
+ {
1006
+ size_t c = poly_view<T>::cols();
1007
+ size_t t = poly_view<T>::unit_size();
1008
+ T y[t]; Int s = {0, t};
1009
+ poly_view<T> v(y, s);
1010
+ for (size_t j = 0; j < c; j++) {
1011
+ Int J(1,j,0);
1012
+ if (j == 0) v = (*this)[J][J];
1013
+ else v *= (*this)[J][J];
1014
+ }
1015
+ return poly_array<T>(y, s);
1016
+ }
1017
+ template <typename S> void solve(poly_view<S>& p, poly_view<S>& a)
1018
+ {
1019
+ plu_subst<T,S>(*this, sign, p, a);
1020
+ }
1021
+ char *to_s() const
1022
+ {
1023
+ char buf[1024];
1024
+ char *c = buf;
1025
+ const poly_view<T>& v = *this;
1026
+ char *s = v.to_s();
1027
+ sprintf(c, "%s.lu", s); while(*c)++c;
1028
+ delete[] s;
1029
+ int n = c - buf;
1030
+ c = new char[n + 1];
1031
+ strcpy(c, buf);
1032
+ return c;
1033
+ }
1034
+ void print(const char *end = NULL) const {
1035
+ char *s = this->to_s();
1036
+ char f[32] = {"%s"};
1037
+ char *c = f; while(*c)++c;
1038
+ if (end) sprintf(c, "%s", end);
1039
+ fprintf(stdout, f, s);
1040
+ delete[] s;
1041
+ }
1042
+ // end poly_array_lu;
1043
+ };
1044
+
1045
+ template <typename T>
1046
+ void Kronecker(const poly_view<T>& p, const poly_view<T>& q, poly_view<T>& r)
1047
+ {
1048
+ if (r.is_atom()) r = p * q;
1049
+ else
1050
+ {
1051
+ const Int& u = p;
1052
+ const Int& v = q;
1053
+ int s = u[0], t = v[0];
1054
+ for (int i = 0; i < s; i++) {
1055
+ Int L(1, i, 0);
1056
+ for (int j = 0; j < t; j++) {
1057
+ Int J(1, j, 0), K(1, i*t+j, 0);
1058
+ poly_view<T> pdr = p[L], qdr = q[J], rdr = r[K];
1059
+ Kronecker(pdr, qdr, rdr);
1060
+ }
1061
+ }
1062
+ }
1063
+ }
1064
+
1065
+ template <typename T>
1066
+ poly_array<T> operator^(const poly_array<T>& p, const poly_array<T>& q)
1067
+ {
1068
+ const Int& ps = p;
1069
+ const Int& qs = q;
1070
+ Int rs = ps * qs;
1071
+ int len = rs.data_size();
1072
+ T result[len];
1073
+ poly_view<T> pv(p), qv(q), rv(result, rs);
1074
+ Kronecker(pv, qv, rv);
1075
+ return poly_array<T>(result, rs);
1076
+ }
1077
+
1078
+ typedef poly_array<double> Poly_array;
1079
+ typedef poly_view<double> Poly_view;
1080
+ typedef poly_array_lu<double> Matrix_LU;
1081
+
1082
+ /*******************************************************************************
1083
+ comb_array<T>(T*,N,S1,...,SN,A);
1084
+ {<{S1,...,SN},A>,[(S1,...),...],...,[(SN,...),...]}
1085
+ *******************************************************************************/
1086
+ template<typename T = double> class comb_array : public Int
1087
+ {
1088
+ template <class> friend class comb_view;
1089
+
1090
+ const T *data;
1091
+
1092
+ void init_data(const T *dat)
1093
+ {
1094
+ if (dat) {
1095
+ size_t s = this->comb_size();
1096
+ T *dt = new T[s];
1097
+ for (size_t i = 0; i < s; ++i) dt[i] = dat[i];
1098
+ data = dt;
1099
+ } else {
1100
+ size_t N = this->grid();
1101
+ for (size_t i = 0; i <= N; ++i) Int::w[i] = 0;
1102
+ data = NULL;
1103
+ }
1104
+ }
1105
+
1106
+ public:
1107
+ // Atom constructor
1108
+ comb_array(const T *dat) : Int(Atom, 1) { init_data(dat); }
1109
+ // General constructor
1110
+ template <class... Args>
1111
+ comb_array(const T *dat, int n, Args... cdr) : Int(n, cdr...) { init_data(dat); }
1112
+ comb_array(const T *dat, int n, int *c) : Int(n, c) { init_data(dat); }
1113
+ comb_array(const T *dat, int n, int *c, int t) : Int(n, c, t) { init_data(dat); }
1114
+ comb_array(const T *dat, const Int& b) : Int(b) { init_data(dat); }
1115
+ // copy constructor
1116
+ comb_array(const comb_array& ba) : Int(ba) { init_data(ba.data); }
1117
+ // destructor
1118
+ ~comb_array() {delete[] data;}
1119
+ // substitution operator
1120
+ comb_array& operator=(const comb_array& ba)
1121
+ {
1122
+ if (this != &ba) {
1123
+ delete data;
1124
+ Int::operator=(ba);
1125
+ init_data(ba.data);
1126
+ }
1127
+ return *this;
1128
+ }
1129
+ const T* operator[](int i) const
1130
+ {
1131
+ int s = this->cast_size(i);
1132
+ return &data[s];
1133
+ }
1134
+ int operator()(int i) const
1135
+ {
1136
+ return Int::operator[](i);
1137
+ }
1138
+ char *to_s() const
1139
+ {
1140
+ char buf[1024];
1141
+ char *c = buf;
1142
+ const Int& p = *this;
1143
+ char *s = p.to_s();
1144
+ sprintf(c, "{%s,", s); while(*c)++c;
1145
+ delete[] s;
1146
+ int N = p.grid(), n = 0, A = p.unit_size();
1147
+ if (N > 0) for (int i = 0; i < N; ++i) {
1148
+ sprintf(c++, "[");
1149
+ int l = p[i];
1150
+ for (int j = 0; j < l; ++j) {
1151
+ const T *pos = &data[n+j*A];
1152
+ if (A > 1) sprintf(c++, "(");
1153
+ for (int a = 0; a < A; ++a) {
1154
+ sprintg(c, pos[a]); while(*c)++c;
1155
+ if (a < A-1) {sprintf(c++, ",");}
1156
+ }
1157
+ if (A > 1) {sprintf(c++, ")");}
1158
+ if (j < l-1) {sprintf(c++, ",");}
1159
+ }
1160
+ sprintf(c++, "]");
1161
+ if (i < N-1) {sprintf(c++, ",");}
1162
+ n += l * A;
1163
+ } else
1164
+ poly_to_s<T>(c, N, p.w, data);
1165
+ sprintf(c++, "}");
1166
+ n = c - buf;
1167
+ c = new char[n + 1];
1168
+ strcpy(c, buf);
1169
+ return c;
1170
+ }
1171
+ void print(const char *end = NULL) const {
1172
+ char *s = this->to_s();
1173
+ char f[32] = {"%s"};
1174
+ char *c = f; while(*c)++c;
1175
+ if (end) sprintf(c, "%s", end);
1176
+ fprintf(stdout, f, s);
1177
+ delete[] s;
1178
+ }
1179
+ // end of comb_array;
1180
+ };
1181
+
1182
+ template<typename T = double> class comb_view : public Int
1183
+ {
1184
+
1185
+ const T *data;
1186
+
1187
+ public:
1188
+ // Atom constructor
1189
+ comb_view(const T *dat) : Int(Atom, 1), data(dat) {}
1190
+ comb_view(const T *dat, int n) : Int(Atom, n), data(dat) {}
1191
+ // General constructor
1192
+ template <class... Args>
1193
+ comb_view(const T *dat, int n, Args... cdr) : Int(n, cdr...), data(dat) {}
1194
+ comb_view(const T *dat, int n, int *c) : Int(n, c), data(dat) {}
1195
+ comb_view(const T *dat, int n, int *c, int t) : Int(n, c, t), data(dat) {}
1196
+ comb_view(const T *dat, const Int& b) : Int(b), data(dat) {}
1197
+ comb_view(const comb_array<T>& ca) : Int(ca), data(ca.data) {}
1198
+ // copy constructor
1199
+ comb_view(const comb_view& ba) : Int(ba), data(ba.data) {}
1200
+ // destructor
1201
+ // substitution operator
1202
+ comb_view& operator=(const comb_view& ba)
1203
+ {
1204
+ if (this != &ba) {
1205
+ int s = this->comb_size();
1206
+ int t = ba.comb_size();
1207
+ if (s != t) throw "size mismatch, comb_view = ";
1208
+ for (int i = 0; i < s; ++i) data[i] = ba.data[i];
1209
+ }
1210
+ return *this;
1211
+ }
1212
+ const T* operator[](int i) const
1213
+ {
1214
+ int n = this->is_atom() ? *Int::w : Int::N;
1215
+ if (i < 0 || i >= n) throw "out of range, comb_view[]";
1216
+ int s = this->cast_size(i);
1217
+ return &data[s];
1218
+ }
1219
+ int operator()(int i) const
1220
+ {
1221
+ if (i < 0 || i > Int::N) throw "out of range, comb_view()";
1222
+ return Int::operator[](i);
1223
+ }
1224
+ char *to_s() const
1225
+ {
1226
+ char buf[1024];
1227
+ char *c = buf;
1228
+ const Int& p = *this;
1229
+ char *s = p.to_s();
1230
+ sprintf(c, "{%s,", s); while(*c)++c;
1231
+ delete[] s;
1232
+ int N = p.grid(), n = 0, A = p.unit_size();
1233
+ if (N > 0) for (int i = 0; i < N; ++i) {
1234
+ sprintf(c, "@["); while(*c)++c;
1235
+ int l = p[i];
1236
+ for (int j = 0; j < l; ++j) {
1237
+ const T *pos = &data[n+j*A];
1238
+ if (A > 1) {sprintf(c++, "(");}
1239
+ for (int a = 0; a < A; ++a) {
1240
+ sprintg(c, pos[a]); while(*c)++c;
1241
+ if (a < A-1) {sprintf(c++, ",");}
1242
+ }
1243
+ if (A > 1) {sprintf(c++, ")");}
1244
+ if (j < l-1) {sprintf(c++, ",");}
1245
+ }
1246
+ sprintf(c++, "]");
1247
+ if (i < N-1) {sprintf(c++, ",");}
1248
+ n += l * A;
1249
+ } else {
1250
+ sprintf(c++, "@");
1251
+ poly_to_s<T>(c, N, p.w, data);
1252
+ }
1253
+ sprintf(c++, "}");
1254
+ n = c - buf;
1255
+ c = new char[n + 1];
1256
+ strcpy(c, buf);
1257
+ return c;
1258
+ }
1259
+ void print(const char *end = NULL) const {
1260
+ char *s = this->to_s();
1261
+ char f[32] = {"%s"};
1262
+ char *c = f; while(*c)++c;
1263
+ if (end) sprintf(c, "%s", end);
1264
+ fprintf(stdout, f, s);
1265
+ delete[] s;
1266
+ }
1267
+ // end of comb_view;
1268
+ };
1269
+
1270
+ template<typename T> class comp_array : public Int
1271
+ {
1272
+ T *data;
1273
+
1274
+ public:
1275
+ // mono constructor
1276
+ comp_array(T *dat, int o, int s, int k = 1) : Int(2, o, s, k), data(new T[s*k])
1277
+ {
1278
+ size_t sk = s * k;
1279
+ for (size_t i = 0; i < sk; ++i) data[i] = dat[i];
1280
+ }
1281
+ // General constructor
1282
+ comp_array(T *dat, int n, int *s) : Int(n, s)
1283
+ {
1284
+ int N = this->grid();
1285
+ size_t sk = this->cast_size(N, N/2);
1286
+ data = new T[sk];
1287
+ memcpy(data, dat, sk * sizeof(T));
1288
+ }
1289
+ comp_array(T *dat, int n, int *s, int k) : Int(n, s, k)
1290
+ {
1291
+ int N = this->grid();
1292
+ size_t sk = this->cast_size(N, N/2);
1293
+ data = new T[sk];
1294
+ memcpy(data, dat, sk * sizeof(T));
1295
+ }
1296
+ // copy constructor
1297
+ comp_array(const comp_array& pa) : Int(pa)
1298
+ {
1299
+ int N = this->grid();
1300
+ size_t sk = this->cast_size(N, N/2);
1301
+ data = new T[sk];
1302
+ memcpy(data, pa.data, sk * sizeof(T));
1303
+ }
1304
+ // destructor
1305
+ ~comp_array() {delete data;}
1306
+ // substitution operator
1307
+ comp_array& operator=(const comp_array& pa)
1308
+ {
1309
+ if (this != &pa) {
1310
+ delete data;
1311
+ Int::operator=(pa);
1312
+ int N = this->grid();
1313
+ size_t sk = this->cast_size(N, N/2);
1314
+ data = new T[sk];
1315
+ memcpy(data, pa.data, sk * sizeof(T));
1316
+ }
1317
+ return *this;
1318
+ }
1319
+ // member function
1320
+ Int offset() const
1321
+ {
1322
+ const Int& b = *this;
1323
+ int N = b.grid();
1324
+ return Int(N/2, b.w, 0);
1325
+ }
1326
+ Int size() const
1327
+ {
1328
+ const Int& b = *this;
1329
+ int N = b.grid();
1330
+ return Int(N/2, &b.w[N/2], b.unit_size());
1331
+ }
1332
+ comp_view<T> operator[](const Int& p) const
1333
+ {
1334
+ const Int& b = *this;
1335
+ int N = b.grid(), K = b.unit_size();
1336
+ T **nk = new T*[N/2];
1337
+ for (int n = 0, i = 0; i < N/2; ++i) {
1338
+ int s = b[i+N/2];
1339
+ int k = n + p[i];
1340
+ nk[i] = &data[k];
1341
+ n += s * K;
1342
+ }
1343
+ return comp_view<T>(nk, N/2, &(b.w[N/2]), p.w[N/2]);
1344
+ }
1345
+ T* operator[](int i) const
1346
+ {
1347
+ const Int& b = *this;
1348
+ int N = b.grid();
1349
+ return &data[b.cast_size(N/2 + i, N/2)];
1350
+ }
1351
+ int operator() (int i) const
1352
+ {
1353
+ return Int::w[i];
1354
+ }
1355
+ operator T* () {return data;}
1356
+ comp_array operator & (const comp_array& pa)
1357
+ {
1358
+ const Int& bt = *this;
1359
+ const Int& pt = pa;
1360
+ int Nt = bt.grid(), Np = pt.grid();
1361
+ int s[Nt + Np + 1], *sp = s;
1362
+ for (int i = 0; i < Nt/2; ++i) *sp++ = bt[i];
1363
+ for (int i = 0; i < Np/2; ++i) *sp++ = pt[i];
1364
+ for (int i =Nt/2; i < Nt; ++i) *sp++ = bt[i];
1365
+ for (int i =Np/2; i < Np; ++i) *sp++ = pt[i];
1366
+ size_t skt = bt.cast_size(Nt, Nt/2);
1367
+ size_t skp = pt.cast_size(Np, Np/2);
1368
+ T dt[skt + skp], *dp = dt;
1369
+ for (size_t i = 0; i < skt; ++i) *dp++ = data[i];
1370
+ for (size_t i = 0; i < skp; ++i) *dp++ = pa.data[i];
1371
+ return comp_array(dt, Nt + Np, s, bt.unit_size());
1372
+ }
1373
+ char *to_s() const
1374
+ {
1375
+ char buf[1024];
1376
+ char *c = buf;
1377
+ const Int& p = *this;
1378
+ int N = p.grid(), K = p.unit_size();
1379
+ sprintf(c, "{<"); while(*c)++c;
1380
+ if (N > 0) {
1381
+ sprintf(c++, "{");
1382
+ for (int i = 0; i < N/2; ++i) {
1383
+ sprintf(c, "%d", p[i]); while(*c)++c;
1384
+ if (i == N/2-1) sprintf(c++, "}");
1385
+ sprintf(c++, ",");
1386
+ }
1387
+ sprintf(c++, "{");
1388
+ for (int i = N/2; i < N; ++i) {
1389
+ sprintf(c, "%d", p[i]); while(*c)++c;
1390
+ if (i == N-1) sprintf(c++, "}");
1391
+ sprintf(c++, ",");
1392
+ }
1393
+ }
1394
+ sprintf(c, "%d>,",p[N]); while(*c)++c;
1395
+ int n = 0;
1396
+ for (int i = 0; i < N/2; ++i) {
1397
+ int z = p[i + N/2];
1398
+ sprintf(c++, "[");
1399
+ for (int k = 0; k < K; ++k) {
1400
+ sprintf(c++, "(");
1401
+ for (int j = 0; j < z; ++j) {
1402
+ sprintg(c, data[n+z*k+j]); while(*c)++c;
1403
+ if (j < z-1) {sprintf(c++, ",");}
1404
+ }
1405
+ sprintf(c++, ")");
1406
+ if (k < K-1) {sprintf(c++, ",");}
1407
+ }
1408
+ sprintf(c++, "]");
1409
+ if (i < N/2-1) {sprintf(c++, ",");}
1410
+ n += z * K;
1411
+ }
1412
+ sprintf(c++, "}");
1413
+ n = c - buf;
1414
+ c = new char[n + 1];
1415
+ strcpy(c, buf);
1416
+ return c;
1417
+ }
1418
+ void print(const char *end = NULL) const {
1419
+ char *s = this->to_s();
1420
+ char f[32] = {"%s"};
1421
+ char *c = f; while(*c)++c;
1422
+ if (end) sprintf(c, "%s", end);
1423
+ fprintf(stdout, f, s);
1424
+ delete[] s;
1425
+ }
1426
+ // end of comp_array;
1427
+ };
1428
+
1429
+ template<typename T> class comp_view : public Int
1430
+ {
1431
+ T **data;
1432
+ public:
1433
+ template <class... Args>
1434
+ comp_view(T **dat, int n, int car, Args... cdr) : Int(n, car, cdr...), data(dat) {}
1435
+ comp_view(T **dat, int n, const int *c ) : Int(n, c ), data(dat) {}
1436
+ comp_view(T **dat, int n, const int *c, int t ) : Int(n, c, t ), data(dat) {}
1437
+ comp_view(T **dat, const Int& b ) : Int(b ), data(dat) {}
1438
+ ~comp_view() {delete[] data;}
1439
+ T operator * () const
1440
+ {
1441
+ return coeff(data, Int::w, this->grid());
1442
+ }
1443
+ T operator[](int j) const
1444
+ {
1445
+ return coeff(data, Int::w, this->grid(), j);
1446
+ }
1447
+ T operator[](T *ds) const
1448
+ {
1449
+ return total_derive(data, Int::w, this->grid(), this->unit_size()-1, ds);
1450
+ }
1451
+ T operator () (T dh, int j = 0) const
1452
+ {
1453
+ const Int& p = *this;
1454
+ int k = p.unit_size();
1455
+ T sum = 0.0;
1456
+ T *ds = data[j];
1457
+ int c = p[j] * k;
1458
+ for (int i = k; i > 0; --i)
1459
+ sum = (sum + ds[c -= p[j]]) * dh / (T)i;
1460
+ return sum;
1461
+ }
1462
+
1463
+ T taylor(T dh, int j = 0) const
1464
+ {
1465
+ const Int& p = *this;
1466
+ int k = p.unit_size();
1467
+ T sum = 0.0;
1468
+ T *ds = data[j];
1469
+ int c = p[j] * k;
1470
+ for (int i = k; i > 0; --i)
1471
+ sum = sum * dh / (T)i + ds[c -= p[j]];
1472
+ return sum;
1473
+ }
1474
+ char *to_s() const
1475
+ {
1476
+ char buf[1024];
1477
+ char *c = buf;
1478
+ const Int& p = *this;
1479
+ int N = p.grid();
1480
+ int K = p.unit_size();
1481
+ char *s = p.to_s();
1482
+ sprintf(c, "{%s", s); while(*c)++c;
1483
+ delete[] s;
1484
+ sprintf(c, "@["); while(*c)++c;
1485
+ for (int i = 0; i < N; ++i) {
1486
+ if (K > 1) sprintf(c++, "[");
1487
+ for (int j = 0; j < K; ++j) {
1488
+ sprintg(c, data[i][j*p[i]]); while(*c)++c;
1489
+ if (j < K-1) sprintf(c++, ",");
1490
+ }
1491
+ if (K > 1) sprintf(c++, "]");
1492
+ if ( i < N-1) sprintf(c++, ",");
1493
+ }
1494
+ sprintf(c++, "]");
1495
+ int n = c - buf;
1496
+ c = new char[n + 1];
1497
+ strcpy(c, buf);
1498
+ return c;
1499
+ }
1500
+ void print(const char *end = NULL) const {
1501
+ char *s = this->to_s();
1502
+ char f[32] = {"%s"};
1503
+ char *c = f; while(*c)++c;
1504
+ if (end) sprintf(c, "%s", end);
1505
+ fprintf(stdout, f, s);
1506
+ delete[] s;
1507
+ }
1508
+ // end of comp_view;
1509
+ };
1510
+
1511
+ template <typename T>
1512
+ bool xvalue(int &i, T &x, const T *X, T &t, int &l, int L, int &d, int p, bool F)
1513
+ {
1514
+ bool f = false;
1515
+ if (F) if (d++ == p) {
1516
+ if (++l == L) {
1517
+ f = true;
1518
+ l = 1;
1519
+ } t = (X ? (X[l] - X[l-1]) : 1.0)/p;
1520
+ d = (l == 1) ? 0 : 1;
1521
+ }
1522
+ i = d + (l - 1) * p;
1523
+ x = (X ? X[l - 1] : l - 1) + d * t;
1524
+ return f;
1525
+ }
1526
+
1527
+ template <typename T> class poly_index
1528
+ {
1529
+ int N, *index, *Le, *Lc, *Nc, Dx;
1530
+ T *value, *Dt; const T **X; Int *e;
1531
+ public:
1532
+ poly_index(const comb_array<T>& x, int Dp)
1533
+ {
1534
+ const Int& end = x; N = end.grid(); int Np[N];
1535
+ index = new int[N*4]; Le = index + N; Lc = Le + N; Nc = Lc + N;
1536
+ value = new T[N*2]; Dt = value + N; X = new const T*[N];
1537
+ for (int i = 0; i < N; i++) {
1538
+ Np[i] =(end[i] - 1) * Dp + 1;
1539
+ Le[i] = end[i]; X[i] = x[i];
1540
+ Lc[i] = 1; Nc[i] = 0;
1541
+ Dt[i] = (X[i] ? (X[i][1] - X[i][0]) : 1.0) / Dp;
1542
+ xvalue(index[i], value[i], X[i], Dt[i], Lc[i], Le[i], Nc[i], Dp, false);
1543
+ } Dx = Dp;
1544
+ e = new Int(N, Np, 1);
1545
+ }
1546
+ ~poly_index() {delete e; delete X; delete value; delete index;}
1547
+ poly_index& operator++()
1548
+ {
1549
+ bool f = true;
1550
+ for (int i = N-1; i >= 0; --i)
1551
+ f = xvalue(index[i], value[i], X[i], Dt[i], Lc[i], Le[i], Nc[i], Dx, f);
1552
+ return *this;
1553
+ }
1554
+ int index_size() // return Npx;
1555
+ {
1556
+ return e->grid_size();
1557
+ }
1558
+ int index_value() // convert index to number;
1559
+ {
1560
+ Int i(N, index, 0);
1561
+ return (*e) && i;
1562
+ }
1563
+ Int get_index() {return Int(N, index, 0);}
1564
+ poly<T> get_value() {return poly<T>(N, value, 0);}
1565
+ // end of poly_index
1566
+ };
1567
+
1568
+ #endif