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.
- checksums.yaml +7 -0
- data/Gemfile +5 -0
- data/README.md +34 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ext/pspline/basis.cpp +351 -0
- data/ext/pspline/example/exbspline.ps +2194 -0
- data/ext/pspline/example/exbspline.rb +36 -0
- data/ext/pspline/example/excspline.ps +2985 -0
- data/ext/pspline/example/excspline.rb +36 -0
- data/ext/pspline/example/exdspline.ps +2846 -0
- data/ext/pspline/example/exdspline.rb +33 -0
- data/ext/pspline/example/exfspline.rb +66 -0
- data/ext/pspline/example/exfspline1.rb +40 -0
- data/ext/pspline/example/expspline.ps +3299 -0
- data/ext/pspline/example/expspline.rb +29 -0
- data/ext/pspline/example/expspline1.rb +29 -0
- data/ext/pspline/example/expspline2.rb +47 -0
- data/ext/pspline/example/exqspline.ps +2957 -0
- data/ext/pspline/example/exqspline.rb +31 -0
- data/ext/pspline/example/exqspline1.rb +31 -0
- data/ext/pspline/example/exqspline2.rb +50 -0
- data/ext/pspline/example/exqspline3.rb +51 -0
- data/ext/pspline/example/exrspline.ps +2812 -0
- data/ext/pspline/example/exrspline.rb +34 -0
- data/ext/pspline/example/exrspline1.rb +34 -0
- data/ext/pspline/example/exrspline2.rb +44 -0
- data/ext/pspline/example/exsspline.ps +1965 -0
- data/ext/pspline/example/exsspline.rb +35 -0
- data/ext/pspline/example/exsspline1.rb +35 -0
- data/ext/pspline/example/extspline.ps +2767 -0
- data/ext/pspline/example/extspline.rb +32 -0
- data/ext/pspline/extconf.rb +7 -0
- data/ext/pspline/fft.cpp +552 -0
- data/ext/pspline/include/basis/basis.h +137 -0
- data/ext/pspline/include/basis/fft.h +152 -0
- data/ext/pspline/include/basis/poly_array.h +1568 -0
- data/ext/pspline/include/basis/pspline.h +506 -0
- data/ext/pspline/include/basis/uspline.h +210 -0
- data/ext/pspline/include/basis/util.h +656 -0
- data/ext/pspline/include/bspline.h +377 -0
- data/ext/pspline/include/bspline_Config.h +2 -0
- data/ext/pspline/plotsub.cpp +132 -0
- data/ext/pspline/pspline.cpp +897 -0
- data/ext/pspline/util.cpp +483 -0
- data/lib/pspline.rb +6 -0
- data/lib/pspline/version.rb +3 -0
- data/pspline.gemspec +25 -0
- 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
|