1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package eu.simuline.octave.type.matrix;
17
18 import eu.simuline.octave.type.OctaveObject;
19 import eu.simuline.octave.type.OctaveDouble;
20
21 import java.util.Arrays;
22 import java.util.List;
23
24
25
26
27
28
29
30
31
32
33
34 public abstract class AbstractGenericMatrix<D, L extends List<?>>
35 implements OctaveObject {
36
37 private static final int PRIME = 31;
38
39
40
41
42 @SuppressWarnings("checkstyle:visibilitymodifier")
43 protected final int[] size;
44
45
46
47
48 @SuppressWarnings("checkstyle:visibilitymodifier")
49 protected L dataL;
50
51
52
53
54
55
56 protected AbstractGenericMatrix(final int... size) {
57 this.size = size.clone();
58 checkSize();
59 int size1 = product(size);
60 this.dataL = newL(size1);
61 }
62
63
64
65
66
67
68
69
70
71 protected AbstractGenericMatrix(D dataA, int... size) {
72 this.size = size;
73 checkSize();
74 int dataLength = initL(dataA, product(size));
75 checkDataSize(dataLength);
76 }
77
78
79
80
81
82
83 protected AbstractGenericMatrix(final AbstractGenericMatrix<D, L> o) {
84 this.size = o.size.clone();
85 int size1 = product(this.size);
86 initL(o.getDataA(), size1);
87 }
88
89
90
91
92
93 private void checkSize() throws IllegalArgumentException {
94 switch (this.size.length) {
95 case 0:
96 throw new IllegalArgumentException("no size");
97 case 1:
98 throw new IllegalArgumentException
99 ("size must have a least 2 dimensions");
100 default:
101 for (final int s : this.size) {
102
103 if (s < 0) {
104 throw new IllegalArgumentException
105 ("element in size less than zero. =" + s);
106 }
107 }
108 }
109 }
110
111
112
113
114
115 private void checkDataSize(int dataLength) {
116 if (product(this.size) > dataLength) {
117 final StringBuilder text = new StringBuilder();
118 text.append("length of data(");
119 text.append(dataLength);
120 text.append(") is smaller than size([");
121 boolean first = true;
122 for (final int i : this.size) {
123 if (first) {
124 first = false;
125 } else {
126 text.append(", ");
127 }
128 text.append(i);
129 }
130 text.append("])");
131 throw new IllegalArgumentException(text.toString());
132 }
133 }
134
135
136
137
138
139
140
141
142
143
144 protected abstract L newL(int size);
145
146
147 protected abstract int initL(D data, int size);
148
149
150
151
152
153 public final int dataSize() {
154 return this.dataL.size();
155 }
156
157
158
159
160
161 protected abstract D getDataA();
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177 public abstract void setPlain(String value, int pos);
178
179
180
181
182
183 private static int product(final int... ns) {
184 int p = 1;
185 for (final int n : ns) {
186
187 p *= n;
188 }
189 return p;
190 }
191
192
193
194
195
196
197
198
199
200
201
202
203 public final void resizeUp(final int... pos) {
204 if (this.size.length != pos.length) {
205 throw new UnsupportedOperationException
206 ("Change in number of dimensions not supported (" + size.length
207 + "!=" + pos.length + ")");
208 }
209
210 if (this.size.length == 0) {
211
212 return;
213 }
214
215 int[] orgSize = this.size.clone();
216 boolean resizeNeeded = false;
217 for (int idx = 0; idx < this.size.length; idx++) {
218 if (pos[idx] > this.size[idx]) {
219 this.size[idx] = pos[idx];
220 resizeNeeded = true;
221 }
222 }
223
224
225 if (!resizeNeeded) {
226 return;
227 }
228
229
230 final int cpyLen = orgSize[0];
231 final int osp = product(orgSize);
232
233
234 D dataInL = getDataA();
235 this.dataL = newL(product(this.size));
236 int idxSrc = 0;
237 int idxTrg = 0;
238 int[] idxTrgMulti = new int[orgSize.length];
239 int idxIdx;
240 int lenUnitGap;
241 while (idxSrc < osp) {
242 System.arraycopy(dataInL, idxSrc,
243 getDataA(), idxTrg, cpyLen);
244 idxSrc += cpyLen;
245
246
247 idxIdx = 1;
248 lenUnitGap = this.size[0];
249 while (idxIdx < orgSize.length
250 && idxTrgMulti[idxIdx] >= orgSize[idxIdx] - 1) {
251 assert idxTrgMulti[idxIdx] == orgSize[idxIdx] - 1;
252
253 idxTrg -= lenUnitGap * idxTrgMulti[idxIdx];
254 idxTrgMulti[idxIdx] = 0;
255
256 lenUnitGap *= this.size[idxIdx];
257 idxIdx++;
258 }
259 assert idxIdx == orgSize.length
260 || idxTrgMulti[idxIdx] < orgSize[idxIdx];
261
262 if (idxIdx >= orgSize.length) {
263 break;
264 }
265
266
267 idxTrg += lenUnitGap;
268 idxTrgMulti[idxIdx]++;
269 }
270 }
271
272
273
274
275
276 public final int pos2ind(final int... pos) {
277 int idx = 0;
278 int factor = 1;
279 for (int dim = 0; dim < pos.length; ++dim) {
280 if (pos[dim] > this.size[dim]) {
281 throw new IndexOutOfBoundsException
282 ("pos exceeded dimension for dimension " +
283 dim + " (" + pos[dim] + " > " + this.size[dim] + ")");
284 }
285 idx += (pos[dim] - 1) * factor;
286 factor *= this.size[dim];
287 }
288 return idx;
289 }
290
291
292
293
294 public abstract String getPlainString(int pos);
295
296 public final int getSizeLength() {
297 return this.size.length;
298 }
299
300
301
302
303
304
305 public final int getSize(final int i) {
306 return this.size[i - 1];
307 }
308
309 @Override
310 public final int hashCode() {
311 int result = 1;
312 result = PRIME * result +
313 ((this.dataL == null) ? 0 : this.dataL.hashCode());
314 result = PRIME * result + Arrays.hashCode(this.size);
315 return result;
316 }
317
318 @SuppressWarnings("unchecked")
319 @Override
320 public final boolean equals(final Object obj) {
321 if (this == obj) {
322 return true;
323 }
324 if (obj == null || getClass() != obj.getClass()) {
325 return false;
326 }
327 final AbstractGenericMatrix<D, List<?>> other =
328 (AbstractGenericMatrix<D, List<?>>) obj;
329 if (!Arrays.equals(this.size, other.size)) {
330 return false;
331 }
332
333 assert this.dataL.size() == product(this.size);
334 return this.dataL.equals(other.dataL);
335 }
336
337 public String toString() {
338 StringBuilder res = new StringBuilder();
339 res.append("<Matrix size='");
340 res.append(Arrays.toString(this.size));
341 res.append("'>\n");
342 res.append(this.dataL);
343 res.append("</Matrix>\n");
344 return res.toString();
345 }
346
347
348 public abstract OctaveObject shallowCopy();
349
350 public static void main(String[] args) {
351 System.out.println("R" + product());
352 }
353
354 }