| 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 | 2 | 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 | 1062 | protected AbstractGenericMatrix(final int... size) { |
| 57 | 1062 | this.size = size.clone(); |
| 58 | 1062 | checkSize(); |
| 59 | 1058 | int size1 = product(size); |
| 60 | 1058 | this.dataL = newL(size1); |
| 61 | 1058 | } |
| 62 | |
|
| 63 | |
|
| 64 | |
|
| 65 | |
|
| 66 | |
|
| 67 | |
|
| 68 | |
|
| 69 | |
|
| 70 | |
|
| 71 | 156 | protected AbstractGenericMatrix(D dataA, int... size) { |
| 72 | 156 | this.size = size; |
| 73 | 156 | checkSize(); |
| 74 | 156 | int dataLength = initL(dataA, product(size)); |
| 75 | 156 | checkDataSize(dataLength); |
| 76 | 154 | } |
| 77 | |
|
| 78 | |
|
| 79 | |
|
| 80 | |
|
| 81 | |
|
| 82 | |
|
| 83 | 358 | protected AbstractGenericMatrix(final AbstractGenericMatrix<D, L> o) { |
| 84 | 358 | this.size = o.size.clone(); |
| 85 | 358 | int size1 = product(this.size); |
| 86 | 358 | initL(o.getDataA(), size1); |
| 87 | 358 | } |
| 88 | |
|
| 89 | |
|
| 90 | |
|
| 91 | |
|
| 92 | |
|
| 93 | |
private void checkSize() throws IllegalArgumentException { |
| 94 | 1218 | switch (this.size.length) { |
| 95 | |
case 0: |
| 96 | 0 | throw new IllegalArgumentException("no size"); |
| 97 | |
case 1: |
| 98 | 4 | throw new IllegalArgumentException |
| 99 | |
("size must have a least 2 dimensions"); |
| 100 | |
default: |
| 101 | 4340 | for (final int s : this.size) { |
| 102 | |
|
| 103 | 3126 | if (s < 0) { |
| 104 | 0 | throw new IllegalArgumentException |
| 105 | |
("element in size less than zero. =" + s); |
| 106 | |
} |
| 107 | |
} |
| 108 | |
} |
| 109 | 1214 | } |
| 110 | |
|
| 111 | |
|
| 112 | |
|
| 113 | |
|
| 114 | |
|
| 115 | |
private void checkDataSize(int dataLength) { |
| 116 | 156 | if (product(this.size) > dataLength) { |
| 117 | 2 | final StringBuilder text = new StringBuilder(); |
| 118 | 2 | text.append("length of data("); |
| 119 | 2 | text.append(dataLength); |
| 120 | 2 | text.append(") is smaller than size(["); |
| 121 | 2 | boolean first = true; |
| 122 | 8 | for (final int i : this.size) { |
| 123 | 6 | if (first) { |
| 124 | 2 | first = false; |
| 125 | |
} else { |
| 126 | 4 | text.append(", "); |
| 127 | |
} |
| 128 | 6 | text.append(i); |
| 129 | |
} |
| 130 | 2 | text.append("])"); |
| 131 | 2 | throw new IllegalArgumentException(text.toString()); |
| 132 | |
} |
| 133 | 154 | } |
| 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 | 6598 | 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 | 43250 | int p = 1; |
| 185 | 131116 | for (final int n : ns) { |
| 186 | |
|
| 187 | 87866 | p *= n; |
| 188 | |
} |
| 189 | 43250 | return p; |
| 190 | |
} |
| 191 | |
|
| 192 | |
|
| 193 | |
|
| 194 | |
|
| 195 | |
|
| 196 | |
|
| 197 | |
|
| 198 | |
|
| 199 | |
|
| 200 | |
|
| 201 | |
|
| 202 | |
|
| 203 | |
public final void resizeUp(final int... pos) { |
| 204 | 41580 | if (this.size.length != pos.length) { |
| 205 | 0 | throw new UnsupportedOperationException |
| 206 | |
("Change in number of dimensions not supported (" + size.length |
| 207 | |
+ "!=" + pos.length + ")"); |
| 208 | |
} |
| 209 | |
|
| 210 | 41580 | if (this.size.length == 0) { |
| 211 | |
|
| 212 | 0 | return; |
| 213 | |
} |
| 214 | |
|
| 215 | 41580 | int[] orgSize = this.size.clone(); |
| 216 | 41580 | boolean resizeNeeded = false; |
| 217 | 124962 | for (int idx = 0; idx < this.size.length; idx++) { |
| 218 | 83382 | if (pos[idx] > this.size[idx]) { |
| 219 | 20628 | this.size[idx] = pos[idx]; |
| 220 | 20628 | resizeNeeded = true; |
| 221 | |
} |
| 222 | |
} |
| 223 | |
|
| 224 | |
|
| 225 | 41580 | if (!resizeNeeded) { |
| 226 | 21010 | return; |
| 227 | |
} |
| 228 | |
|
| 229 | |
|
| 230 | 20570 | final int cpyLen = orgSize[0]; |
| 231 | 20570 | final int osp = product(orgSize); |
| 232 | |
|
| 233 | |
|
| 234 | 20570 | D dataInL = getDataA(); |
| 235 | 20570 | this.dataL = newL(product(this.size)); |
| 236 | 20570 | int idxSrc = 0; |
| 237 | 20570 | int idxTrg = 0; |
| 238 | 20570 | int[] idxTrgMulti = new int[orgSize.length]; |
| 239 | |
int idxIdx; |
| 240 | |
int lenUnitGap; |
| 241 | 34143180 | while (idxSrc < osp) { |
| 242 | 68286276 | System.arraycopy(dataInL, idxSrc, |
| 243 | 34143138 | getDataA(), idxTrg, cpyLen); |
| 244 | 34143138 | idxSrc += cpyLen; |
| 245 | |
|
| 246 | |
|
| 247 | 34143138 | idxIdx = 1; |
| 248 | 34143138 | lenUnitGap = this.size[0]; |
| 249 | 34163762 | while (idxIdx < orgSize.length |
| 250 | |
&& idxTrgMulti[idxIdx] >= orgSize[idxIdx] - 1) { |
| 251 | 20624 | assert idxTrgMulti[idxIdx] == orgSize[idxIdx] - 1; |
| 252 | |
|
| 253 | 20624 | idxTrg -= lenUnitGap * idxTrgMulti[idxIdx]; |
| 254 | 20624 | idxTrgMulti[idxIdx] = 0; |
| 255 | |
|
| 256 | 20624 | lenUnitGap *= this.size[idxIdx]; |
| 257 | 20624 | idxIdx++; |
| 258 | |
} |
| 259 | 34143138 | assert idxIdx == orgSize.length |
| 260 | |
|| idxTrgMulti[idxIdx] < orgSize[idxIdx]; |
| 261 | |
|
| 262 | 34143138 | if (idxIdx >= orgSize.length) { |
| 263 | 20528 | break; |
| 264 | |
} |
| 265 | |
|
| 266 | |
|
| 267 | 34122610 | idxTrg += lenUnitGap; |
| 268 | 34122610 | idxTrgMulti[idxIdx]++; |
| 269 | |
} |
| 270 | 20570 | } |
| 271 | |
|
| 272 | |
|
| 273 | |
|
| 274 | |
|
| 275 | |
|
| 276 | |
public final int pos2ind(final int... pos) { |
| 277 | 43788 | int idx = 0; |
| 278 | 43788 | int factor = 1; |
| 279 | 134688 | for (int dim = 0; dim < pos.length; ++dim) { |
| 280 | 90932 | if (pos[dim] > this.size[dim]) { |
| 281 | 28 | throw new IndexOutOfBoundsException |
| 282 | |
("pos exceeded dimension for dimension " + |
| 283 | |
dim + " (" + pos[dim] + " > " + this.size[dim] + ")"); |
| 284 | |
} |
| 285 | 90900 | idx += (pos[dim] - 1) * factor; |
| 286 | 90900 | factor *= this.size[dim]; |
| 287 | |
} |
| 288 | 43756 | return idx; |
| 289 | |
} |
| 290 | |
|
| 291 | |
|
| 292 | |
|
| 293 | |
|
| 294 | |
public abstract String getPlainString(int pos); |
| 295 | |
|
| 296 | |
public final int getSizeLength() { |
| 297 | 2174 | return this.size.length; |
| 298 | |
} |
| 299 | |
|
| 300 | |
|
| 301 | |
|
| 302 | |
|
| 303 | |
|
| 304 | |
|
| 305 | |
public final int getSize(final int i) { |
| 306 | 2258 | return this.size[i - 1]; |
| 307 | |
} |
| 308 | |
|
| 309 | |
@Override |
| 310 | |
public final int hashCode() { |
| 311 | 0 | int result = 1; |
| 312 | 0 | result = PRIME * result + |
| 313 | 0 | ((this.dataL == null) ? 0 : this.dataL.hashCode()); |
| 314 | 0 | result = PRIME * result + Arrays.hashCode(this.size); |
| 315 | 0 | return result; |
| 316 | |
} |
| 317 | |
|
| 318 | |
@SuppressWarnings("unchecked") |
| 319 | |
@Override |
| 320 | |
public final boolean equals(final Object obj) { |
| 321 | 720 | if (this == obj) { |
| 322 | 0 | return true; |
| 323 | |
} |
| 324 | 720 | if (obj == null || getClass() != obj.getClass()) { |
| 325 | 36 | return false; |
| 326 | |
} |
| 327 | 684 | final AbstractGenericMatrix<D, List<?>> other = |
| 328 | |
(AbstractGenericMatrix<D, List<?>>) obj; |
| 329 | 684 | if (!Arrays.equals(this.size, other.size)) { |
| 330 | 302 | return false; |
| 331 | |
} |
| 332 | |
|
| 333 | 382 | assert this.dataL.size() == product(this.size); |
| 334 | 382 | return this.dataL.equals(other.dataL); |
| 335 | |
} |
| 336 | |
|
| 337 | |
|
| 338 | |
public abstract OctaveObject shallowCopy(); |
| 339 | |
|
| 340 | |
public static void main(String[] args) { |
| 341 | 0 | System.out.println("R" + product()); |
| 342 | 0 | } |
| 343 | |
|
| 344 | |
} |