~ubuntu-branches/ubuntu/maverick/commons-math/maverick

« back to all changes in this revision

Viewing changes to src/main/java/org/apache/commons/math/linear/AbstractFieldMatrix.java

  • Committer: Bazaar Package Importer
  • Author(s): Damien Raude-Morvan
  • Date: 2009-08-22 01:13:25 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20090822011325-hi4peq1ua5weguwn
Tags: 2.0-1
* New upstream release.
* Set Maintainer field to Debian Java Team
* Add myself as Uploaders
* Switch to Quilt patch system:
  - Refresh all patchs
  - Remove B-D on dpatch, Add B-D on quilt
  - Include patchsys-quilt.mk in debian/rules
* Bump Standards-Version to 3.8.3:
  - Add a README.source to describe patch system
* Maven POMs:
  - Add a Build-Depends-Indep dependency on maven-repo-helper
  - Use mh_installpom and mh_installjar to install the POM and the jar to the
    Maven repository
* Use default-jdk/jre:
  - Depends on java5-runtime-headless
  - Build-Depends on default-jdk
  - Use /usr/lib/jvm/default-java as JAVA_HOME
* Move api documentation to /usr/share/doc/libcommons-math-java/api
* Build-Depends on junit4 instead of junit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
 
3
 * contributor license agreements.  See the NOTICE file distributed with
 
4
 * this work for additional information regarding copyright ownership.
 
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
 
6
 * (the "License"); you may not use this file except in compliance with
 
7
 * the License.  You may obtain a copy of the License at
 
8
 *
 
9
 *      http://www.apache.org/licenses/LICENSE-2.0
 
10
 *
 
11
 * Unless required by applicable law or agreed to in writing, software
 
12
 * distributed under the License is distributed on an "AS IS" BASIS,
 
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
14
 * See the License for the specific language governing permissions and
 
15
 * limitations under the License.
 
16
 */
 
17
 
 
18
package org.apache.commons.math.linear;
 
19
 
 
20
import java.lang.reflect.Array;
 
21
import java.util.Arrays;
 
22
 
 
23
import org.apache.commons.math.Field;
 
24
import org.apache.commons.math.FieldElement;
 
25
import org.apache.commons.math.MathRuntimeException;
 
26
 
 
27
/**
 
28
 * Basic implementation of {@link FieldMatrix} methods regardless of the underlying storage.
 
29
 * <p>All the methods implemented here use {@link #getEntry(int, int)} to access
 
30
 * matrix elements. Derived class can provide faster implementations. </p>
 
31
 *
 
32
 * @param <T> the type of the field elements
 
33
 * @version $Revision: 783702 $ $Date: 2009-06-11 04:54:02 -0400 (Thu, 11 Jun 2009) $
 
34
 * @since 2.0
 
35
 */
 
36
public abstract class AbstractFieldMatrix<T extends FieldElement<T>> implements FieldMatrix<T> {
 
37
    
 
38
    /** Field to which the elements belong. */
 
39
    private final Field<T> field;
 
40
 
 
41
    /**
 
42
     * Get the elements type from an array.
 
43
     * @param <T> the type of the field elements
 
44
     * @param d data array
 
45
     * @return field to which array elements belong
 
46
     * @exception IllegalArgumentException if array is empty
 
47
     */
 
48
    protected static <T extends FieldElement<T>> Field<T> extractField(final T[][] d)
 
49
        throws IllegalArgumentException {
 
50
        if (d.length == 0) {
 
51
            throw MathRuntimeException.createIllegalArgumentException("matrix must have at least one row"); 
 
52
        }
 
53
        if (d[0].length == 0) {
 
54
            throw MathRuntimeException.createIllegalArgumentException("matrix must have at least one column"); 
 
55
        }
 
56
        return d[0][0].getField();
 
57
    }
 
58
 
 
59
    /**
 
60
     * Get the elements type from an array.
 
61
     * @param <T> the type of the field elements
 
62
     * @param d data array
 
63
     * @return field to which array elements belong
 
64
     * @exception IllegalArgumentException if array is empty
 
65
     */
 
66
    protected static <T extends FieldElement<T>> Field<T> extractField(final T[] d)
 
67
        throws IllegalArgumentException {
 
68
        if (d.length == 0) {
 
69
            throw MathRuntimeException.createIllegalArgumentException("matrix must have at least one row"); 
 
70
        }
 
71
        return d[0].getField();
 
72
    }
 
73
 
 
74
    /** Build an array of elements.
 
75
     * <p>
 
76
     * Complete arrays are filled with field.getZero()
 
77
     * </p>
 
78
     * @param <T> the type of the field elements
 
79
     * @param field field to which array elements belong
 
80
     * @param rows number of rows
 
81
     * @param columns number of columns (may be negative to build partial
 
82
     * arrays in the same way <code>new Field[rows][]</code> works)
 
83
     * @return a new array
 
84
     */
 
85
    @SuppressWarnings("unchecked")
 
86
    protected static <T extends FieldElement<T>> T[][] buildArray(final Field<T> field,
 
87
                                                                  final int rows,
 
88
                                                                  final int columns) {
 
89
        if (columns < 0) {
 
90
            T[] dummyRow = (T[]) Array.newInstance(field.getZero().getClass(), 0); 
 
91
            return (T[][]) Array.newInstance(dummyRow.getClass(), rows);            
 
92
        }
 
93
        T[][] array =
 
94
            (T[][]) Array.newInstance(field.getZero().getClass(), new int[] { rows, columns });
 
95
        for (int i = 0; i < array.length; ++i) {
 
96
            Arrays.fill(array[i], field.getZero());
 
97
        }
 
98
        return array;
 
99
    }
 
100
 
 
101
    /** Build an array of elements.
 
102
     * <p>
 
103
     * Arrays are filled with field.getZero()
 
104
     * </p>
 
105
     * @param <T> the type of the field elements
 
106
     * @param field field to which array elements belong
 
107
     * @param length of the array
 
108
     * @return a new array
 
109
     */
 
110
    @SuppressWarnings("unchecked")
 
111
    protected static <T extends FieldElement<T>> T[] buildArray(final Field<T> field,
 
112
                                                                final int length) {
 
113
        T[] array = (T[]) Array.newInstance(field.getZero().getClass(), length);
 
114
        Arrays.fill(array, field.getZero());
 
115
        return array;
 
116
    }
 
117
 
 
118
    /**
 
119
     * Constructor for use with Serializable
 
120
     */
 
121
    protected AbstractFieldMatrix() {
 
122
        field = null;
 
123
    }
 
124
    
 
125
    /**
 
126
     * Creates a matrix with no data
 
127
     * @param field field to which the elements belong
 
128
     */
 
129
    protected AbstractFieldMatrix(final Field<T> field) {
 
130
        this.field = field;
 
131
    }
 
132
 
 
133
    /**
 
134
     * Create a new FieldMatrix<T> with the supplied row and column dimensions.
 
135
     *
 
136
     * @param field field to which the elements belong
 
137
     * @param rowDimension  the number of rows in the new matrix
 
138
     * @param columnDimension  the number of columns in the new matrix
 
139
     * @throws IllegalArgumentException if row or column dimension is not positive
 
140
     */
 
141
    protected AbstractFieldMatrix(final Field<T> field,
 
142
                                  final int rowDimension, final int columnDimension)
 
143
        throws IllegalArgumentException {
 
144
        if (rowDimension <= 0 ) {
 
145
            throw MathRuntimeException.createIllegalArgumentException(
 
146
                    "invalid row dimension {0} (must be positive)",
 
147
                    rowDimension);
 
148
        }
 
149
        if (columnDimension <= 0) {
 
150
            throw MathRuntimeException.createIllegalArgumentException(
 
151
                    "invalid column dimension {0} (must be positive)",
 
152
                    columnDimension);
 
153
        }
 
154
        this.field = field;
 
155
    }
 
156
 
 
157
    /** {@inheritDoc} */
 
158
    public Field<T> getField() {
 
159
        return field;
 
160
    }
 
161
 
 
162
    /** {@inheritDoc} */
 
163
    public abstract FieldMatrix<T> createMatrix(final int rowDimension, final int columnDimension)
 
164
        throws IllegalArgumentException;
 
165
 
 
166
    /** {@inheritDoc} */
 
167
    public abstract FieldMatrix<T> copy();
 
168
 
 
169
    /** {@inheritDoc} */
 
170
    public FieldMatrix<T> add(FieldMatrix<T> m) throws IllegalArgumentException {
 
171
 
 
172
        // safety check
 
173
        checkAdditionCompatible(m);
 
174
 
 
175
        final int rowCount    = getRowDimension();
 
176
        final int columnCount = getColumnDimension();
 
177
        final FieldMatrix<T> out = createMatrix(rowCount, columnCount);
 
178
        for (int row = 0; row < rowCount; ++row) {
 
179
            for (int col = 0; col < columnCount; ++col) {
 
180
                out.setEntry(row, col, getEntry(row, col).add(m.getEntry(row, col)));
 
181
            }  
 
182
        }
 
183
 
 
184
        return out;
 
185
 
 
186
    }
 
187
 
 
188
    /** {@inheritDoc} */
 
189
    public FieldMatrix<T> subtract(final FieldMatrix<T> m) throws IllegalArgumentException {
 
190
 
 
191
        // safety check
 
192
        checkSubtractionCompatible(m);
 
193
 
 
194
        final int rowCount    = getRowDimension();
 
195
        final int columnCount = getColumnDimension();
 
196
        final FieldMatrix<T> out = createMatrix(rowCount, columnCount);
 
197
        for (int row = 0; row < rowCount; ++row) {
 
198
            for (int col = 0; col < columnCount; ++col) {
 
199
                out.setEntry(row, col, getEntry(row, col).subtract(m.getEntry(row, col)));
 
200
            }  
 
201
        }
 
202
 
 
203
        return out;
 
204
 
 
205
    }
 
206
 
 
207
    /** {@inheritDoc} */
 
208
    public FieldMatrix<T> scalarAdd(final T d) {
 
209
 
 
210
        final int rowCount    = getRowDimension();
 
211
        final int columnCount = getColumnDimension();
 
212
        final FieldMatrix<T> out = createMatrix(rowCount, columnCount);
 
213
        for (int row = 0; row < rowCount; ++row) {
 
214
            for (int col = 0; col < columnCount; ++col) {
 
215
                out.setEntry(row, col, getEntry(row, col).add(d));
 
216
            }
 
217
        }
 
218
 
 
219
        return out;
 
220
 
 
221
    }
 
222
 
 
223
    /** {@inheritDoc} */
 
224
    public FieldMatrix<T> scalarMultiply(final T d) {
 
225
 
 
226
        final int rowCount    = getRowDimension();
 
227
        final int columnCount = getColumnDimension();
 
228
        final FieldMatrix<T> out = createMatrix(rowCount, columnCount);
 
229
        for (int row = 0; row < rowCount; ++row) {
 
230
            for (int col = 0; col < columnCount; ++col) {
 
231
                out.setEntry(row, col, getEntry(row, col).multiply(d));
 
232
            }
 
233
        }
 
234
 
 
235
        return out;
 
236
 
 
237
    }
 
238
 
 
239
    /** {@inheritDoc} */
 
240
    public FieldMatrix<T> multiply(final FieldMatrix<T> m)
 
241
        throws IllegalArgumentException {
 
242
 
 
243
        // safety check
 
244
        checkMultiplicationCompatible(m);
 
245
 
 
246
        final int nRows = getRowDimension();
 
247
        final int nCols = m.getColumnDimension();
 
248
        final int nSum  = getColumnDimension();
 
249
        final FieldMatrix<T> out = createMatrix(nRows, nCols);
 
250
        for (int row = 0; row < nRows; ++row) {
 
251
            for (int col = 0; col < nCols; ++col) {
 
252
                T sum = field.getZero();
 
253
                for (int i = 0; i < nSum; ++i) {
 
254
                    sum = sum.add(getEntry(row, i).multiply(m.getEntry(i, col)));
 
255
                }
 
256
                out.setEntry(row, col, sum);
 
257
            }
 
258
        }
 
259
 
 
260
        return out;
 
261
 
 
262
    }
 
263
 
 
264
    /** {@inheritDoc} */
 
265
    public FieldMatrix<T> preMultiply(final FieldMatrix<T> m)
 
266
        throws IllegalArgumentException {
 
267
        return m.multiply(this);
 
268
    }
 
269
 
 
270
    /** {@inheritDoc} */
 
271
    public T[][] getData() {
 
272
 
 
273
        final T[][] data = buildArray(field, getRowDimension(), getColumnDimension());
 
274
 
 
275
        for (int i = 0; i < data.length; ++i) {
 
276
            final T[] dataI = data[i];
 
277
            for (int j = 0; j < dataI.length; ++j) {
 
278
                dataI[j] = getEntry(i, j);
 
279
            }
 
280
        }
 
281
 
 
282
        return data;
 
283
 
 
284
    }
 
285
 
 
286
    /** {@inheritDoc} */
 
287
    public FieldMatrix<T> getSubMatrix(final int startRow, final int endRow,
 
288
                                   final int startColumn, final int endColumn)
 
289
        throws MatrixIndexException {
 
290
 
 
291
        checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
 
292
 
 
293
        final FieldMatrix<T> subMatrix =
 
294
            createMatrix(endRow - startRow + 1, endColumn - startColumn + 1);
 
295
        for (int i = startRow; i <= endRow; ++i) {
 
296
            for (int j = startColumn; j <= endColumn; ++j) {
 
297
                subMatrix.setEntry(i - startRow, j - startColumn, getEntry(i, j));
 
298
            }
 
299
        }
 
300
 
 
301
        return subMatrix;
 
302
 
 
303
    }
 
304
 
 
305
    /** {@inheritDoc} */
 
306
    public FieldMatrix<T> getSubMatrix(final int[] selectedRows, final int[] selectedColumns)
 
307
        throws MatrixIndexException {
 
308
 
 
309
        // safety checks
 
310
        checkSubMatrixIndex(selectedRows, selectedColumns);
 
311
 
 
312
        // copy entries
 
313
        final FieldMatrix<T> subMatrix =
 
314
            createMatrix(selectedRows.length, selectedColumns.length);
 
315
        subMatrix.walkInOptimizedOrder(new DefaultFieldMatrixChangingVisitor<T>(field.getZero()) {
 
316
 
 
317
            /** {@inheritDoc} */
 
318
            @Override
 
319
            public T visit(final int row, final int column, final T value) {
 
320
                return getEntry(selectedRows[row], selectedColumns[column]);
 
321
            }
 
322
 
 
323
        });
 
324
 
 
325
        return subMatrix;
 
326
 
 
327
    } 
 
328
 
 
329
    /** {@inheritDoc} */
 
330
    public void copySubMatrix(final int startRow, final int endRow,
 
331
                              final int startColumn, final int endColumn,
 
332
                              final T[][] destination)
 
333
        throws MatrixIndexException, IllegalArgumentException {
 
334
 
 
335
        // safety checks
 
336
        checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
 
337
        final int rowsCount    = endRow + 1 - startRow;
 
338
        final int columnsCount = endColumn + 1 - startColumn;
 
339
        if ((destination.length < rowsCount) || (destination[0].length < columnsCount)) {
 
340
            throw MathRuntimeException.createIllegalArgumentException(
 
341
                    "dimensions mismatch: got {0}x{1} but expected {2}x{3}",
 
342
                    destination.length, destination[0].length,
 
343
                    rowsCount, columnsCount);
 
344
        }
 
345
 
 
346
        // copy entries
 
347
        walkInOptimizedOrder(new DefaultFieldMatrixPreservingVisitor<T>(field.getZero()) {
 
348
 
 
349
            /** Initial row index. */
 
350
            private int startRow;
 
351
 
 
352
            /** Initial column index. */
 
353
            private int startColumn;
 
354
 
 
355
            /** {@inheritDoc} */
 
356
            @Override
 
357
            public void start(final int rows, final int columns,
 
358
                              final int startRow, final int endRow,
 
359
                              final int startColumn, final int endColumn) {
 
360
                this.startRow    = startRow;
 
361
                this.startColumn = startColumn;
 
362
            }
 
363
 
 
364
            /** {@inheritDoc} */
 
365
            @Override
 
366
            public void visit(final int row, final int column, final T value) {
 
367
                destination[row - startRow][column - startColumn] = value;
 
368
            }
 
369
 
 
370
        }, startRow, endRow, startColumn, endColumn);
 
371
 
 
372
    }
 
373
 
 
374
    /** {@inheritDoc} */
 
375
    public void copySubMatrix(int[] selectedRows, int[] selectedColumns, T[][] destination)
 
376
        throws MatrixIndexException, IllegalArgumentException {
 
377
 
 
378
        // safety checks
 
379
        checkSubMatrixIndex(selectedRows, selectedColumns);
 
380
        if ((destination.length < selectedRows.length) ||
 
381
            (destination[0].length < selectedColumns.length)) {
 
382
            throw MathRuntimeException.createIllegalArgumentException(
 
383
                    "dimensions mismatch: got {0}x{1} but expected {2}x{3}",
 
384
                    destination.length, destination[0].length,
 
385
                    selectedRows.length, selectedColumns.length);
 
386
        }
 
387
 
 
388
        // copy entries
 
389
        for (int i = 0; i < selectedRows.length; i++) {
 
390
            final T[] destinationI = destination[i];
 
391
            for (int j = 0; j < selectedColumns.length; j++) {
 
392
                destinationI[j] = getEntry(selectedRows[i], selectedColumns[j]);
 
393
            }
 
394
        }
 
395
 
 
396
    }
 
397
 
 
398
    /** {@inheritDoc} */
 
399
    public void setSubMatrix(final T[][] subMatrix, final int row, final int column) 
 
400
        throws MatrixIndexException {
 
401
 
 
402
        final int nRows = subMatrix.length;
 
403
        if (nRows == 0) {
 
404
            throw MathRuntimeException.createIllegalArgumentException("matrix must have at least one row"); 
 
405
        }
 
406
 
 
407
        final int nCols = subMatrix[0].length;
 
408
        if (nCols == 0) {
 
409
            throw MathRuntimeException.createIllegalArgumentException("matrix must have at least one column"); 
 
410
        }
 
411
 
 
412
        for (int r = 1; r < nRows; ++r) {
 
413
            if (subMatrix[r].length != nCols) {
 
414
                throw MathRuntimeException.createIllegalArgumentException(
 
415
                        "some rows have length {0} while others have length {1}",
 
416
                        nCols, subMatrix[r].length); 
 
417
            }
 
418
        }
 
419
 
 
420
        checkRowIndex(row);
 
421
        checkColumnIndex(column);
 
422
        checkRowIndex(nRows + row - 1);
 
423
        checkColumnIndex(nCols + column - 1);
 
424
 
 
425
        for (int i = 0; i < nRows; ++i) {
 
426
            for (int j = 0; j < nCols; ++j) {
 
427
                setEntry(row + i, column + j, subMatrix[i][j]);
 
428
            }
 
429
        } 
 
430
 
 
431
    }
 
432
 
 
433
    /** {@inheritDoc} */
 
434
    public FieldMatrix<T> getRowMatrix(final int row)
 
435
        throws MatrixIndexException {
 
436
 
 
437
        checkRowIndex(row);
 
438
        final int nCols = getColumnDimension();
 
439
        final FieldMatrix<T> out = createMatrix(1, nCols);
 
440
        for (int i = 0; i < nCols; ++i) {
 
441
            out.setEntry(0, i, getEntry(row, i));
 
442
        }
 
443
 
 
444
        return out;
 
445
 
 
446
    }
 
447
    
 
448
    /** {@inheritDoc} */
 
449
    public void setRowMatrix(final int row, final FieldMatrix<T> matrix)
 
450
        throws MatrixIndexException, InvalidMatrixException {
 
451
 
 
452
        checkRowIndex(row);
 
453
        final int nCols = getColumnDimension();
 
454
        if ((matrix.getRowDimension() != 1) ||
 
455
            (matrix.getColumnDimension() != nCols)) {
 
456
            throw new InvalidMatrixException(
 
457
                    "dimensions mismatch: got {0}x{1} but expected {2}x{3}",
 
458
                    matrix.getRowDimension(), matrix.getColumnDimension(), 1, nCols);
 
459
        }
 
460
        for (int i = 0; i < nCols; ++i) {
 
461
            setEntry(row, i, matrix.getEntry(0, i));
 
462
        }
 
463
 
 
464
    }
 
465
    
 
466
    /** {@inheritDoc} */
 
467
    public FieldMatrix<T> getColumnMatrix(final int column)
 
468
        throws MatrixIndexException {
 
469
 
 
470
        checkColumnIndex(column);
 
471
        final int nRows = getRowDimension();
 
472
        final FieldMatrix<T> out = createMatrix(nRows, 1);
 
473
        for (int i = 0; i < nRows; ++i) {
 
474
            out.setEntry(i, 0, getEntry(i, column));
 
475
        }
 
476
 
 
477
        return out;
 
478
 
 
479
    }
 
480
 
 
481
    /** {@inheritDoc} */
 
482
    public void setColumnMatrix(final int column, final FieldMatrix<T> matrix)
 
483
        throws MatrixIndexException, InvalidMatrixException {
 
484
 
 
485
        checkColumnIndex(column);
 
486
        final int nRows = getRowDimension();
 
487
        if ((matrix.getRowDimension() != nRows) ||
 
488
            (matrix.getColumnDimension() != 1)) {
 
489
            throw new InvalidMatrixException(
 
490
                    "dimensions mismatch: got {0}x{1} but expected {2}x{3}",
 
491
                    matrix.getRowDimension(), matrix.getColumnDimension(), nRows, 1);
 
492
        }
 
493
        for (int i = 0; i < nRows; ++i) {
 
494
            setEntry(i, column, matrix.getEntry(i, 0));
 
495
        }
 
496
 
 
497
    }
 
498
    
 
499
    /** {@inheritDoc} */
 
500
    public FieldVector<T> getRowVector(final int row)
 
501
        throws MatrixIndexException {
 
502
        return new ArrayFieldVector<T>(getRow(row), false);
 
503
    }
 
504
 
 
505
    /** {@inheritDoc} */
 
506
    public void setRowVector(final int row, final FieldVector<T> vector)
 
507
        throws MatrixIndexException, InvalidMatrixException {
 
508
 
 
509
        checkRowIndex(row);
 
510
        final int nCols = getColumnDimension();
 
511
        if (vector.getDimension() != nCols) {
 
512
            throw new InvalidMatrixException(
 
513
                    "dimensions mismatch: got {0}x{1} but expected {2}x{3}",
 
514
                    1, vector.getDimension(), 1, nCols);
 
515
        }
 
516
        for (int i = 0; i < nCols; ++i) {
 
517
            setEntry(row, i, vector.getEntry(i));
 
518
        }
 
519
 
 
520
    }
 
521
    
 
522
    /** {@inheritDoc} */
 
523
    public FieldVector<T> getColumnVector(final int column)
 
524
        throws MatrixIndexException {
 
525
        return new ArrayFieldVector<T>(getColumn(column), false);
 
526
    }
 
527
 
 
528
    /** {@inheritDoc} */
 
529
    public void setColumnVector(final int column, final FieldVector<T> vector)
 
530
        throws MatrixIndexException, InvalidMatrixException {
 
531
 
 
532
        checkColumnIndex(column);
 
533
        final int nRows = getRowDimension();
 
534
        if (vector.getDimension() != nRows) {
 
535
            throw new InvalidMatrixException(
 
536
                    "dimensions mismatch: got {0}x{1} but expected {2}x{3}",
 
537
                    vector.getDimension(), 1, nRows, 1);
 
538
        }
 
539
        for (int i = 0; i < nRows; ++i) {
 
540
            setEntry(i, column, vector.getEntry(i));
 
541
        }
 
542
 
 
543
    }
 
544
    
 
545
    /** {@inheritDoc} */
 
546
    public T[] getRow(final int row)
 
547
        throws MatrixIndexException {
 
548
 
 
549
        checkRowIndex(row);
 
550
        final int nCols = getColumnDimension();
 
551
        final T[] out = buildArray(field, nCols);
 
552
        for (int i = 0; i < nCols; ++i) {
 
553
            out[i] = getEntry(row, i);
 
554
        }
 
555
 
 
556
        return out;
 
557
 
 
558
    }
 
559
 
 
560
    /** {@inheritDoc} */
 
561
    public void setRow(final int row, final T[] array)
 
562
        throws MatrixIndexException, InvalidMatrixException {
 
563
 
 
564
        checkRowIndex(row);
 
565
        final int nCols = getColumnDimension();
 
566
        if (array.length != nCols) {
 
567
            throw new InvalidMatrixException(
 
568
                    "dimensions mismatch: got {0}x{1} but expected {2}x{3}",
 
569
                    1, array.length, 1, nCols);
 
570
        }
 
571
        for (int i = 0; i < nCols; ++i) {
 
572
            setEntry(row, i, array[i]);
 
573
        }
 
574
 
 
575
    }
 
576
    
 
577
    /** {@inheritDoc} */
 
578
    public T[] getColumn(final int column)
 
579
        throws MatrixIndexException {
 
580
 
 
581
        checkColumnIndex(column);
 
582
        final int nRows = getRowDimension();
 
583
        final T[] out = buildArray(field, nRows);
 
584
        for (int i = 0; i < nRows; ++i) {
 
585
            out[i] = getEntry(i, column);
 
586
        }
 
587
 
 
588
        return out;
 
589
 
 
590
    }
 
591
 
 
592
    /** {@inheritDoc} */
 
593
    public void setColumn(final int column, final T[] array)
 
594
        throws MatrixIndexException, InvalidMatrixException {
 
595
 
 
596
        checkColumnIndex(column);
 
597
        final int nRows = getRowDimension();
 
598
        if (array.length != nRows) {
 
599
            throw new InvalidMatrixException(
 
600
                    "dimensions mismatch: got {0}x{1} but expected {2}x{3}",
 
601
                    array.length, 1, nRows, 1);
 
602
        }
 
603
        for (int i = 0; i < nRows; ++i) {
 
604
            setEntry(i, column, array[i]);
 
605
        }
 
606
 
 
607
    }
 
608
    
 
609
    /** {@inheritDoc} */
 
610
    public abstract T getEntry(int row, int column)
 
611
        throws MatrixIndexException;
 
612
 
 
613
    /** {@inheritDoc} */
 
614
    public abstract void setEntry(int row, int column, T value)
 
615
        throws MatrixIndexException;
 
616
 
 
617
    /** {@inheritDoc} */
 
618
    public abstract void addToEntry(int row, int column, T increment)
 
619
        throws MatrixIndexException;
 
620
 
 
621
    /** {@inheritDoc} */
 
622
    public abstract void multiplyEntry(int row, int column, T factor)
 
623
        throws MatrixIndexException;
 
624
 
 
625
    /** {@inheritDoc} */
 
626
    public FieldMatrix<T> transpose() {
 
627
 
 
628
        final int nRows = getRowDimension();
 
629
        final int nCols = getColumnDimension();
 
630
        final FieldMatrix<T> out = createMatrix(nCols, nRows);
 
631
        walkInOptimizedOrder(new DefaultFieldMatrixPreservingVisitor<T>(field.getZero()) {
 
632
 
 
633
            /** {@inheritDoc} */
 
634
            @Override
 
635
            public void visit(final int row, final int column, final T value) {
 
636
                out.setEntry(column, row, value);
 
637
            }
 
638
 
 
639
        });
 
640
 
 
641
        return out;
 
642
 
 
643
    }
 
644
 
 
645
    /** {@inheritDoc} */
 
646
    public boolean isSquare() {
 
647
        return (getColumnDimension() == getRowDimension());
 
648
    }
 
649
 
 
650
    /** {@inheritDoc} */
 
651
    public abstract int getRowDimension();
 
652
 
 
653
    /** {@inheritDoc} */
 
654
    public abstract int getColumnDimension();
 
655
 
 
656
    /** {@inheritDoc} */
 
657
    public T getTrace()
 
658
        throws NonSquareMatrixException {
 
659
        final int nRows = getRowDimension();
 
660
        final int nCols = getColumnDimension();
 
661
        if (nRows != nCols) {
 
662
            throw new NonSquareMatrixException(nRows, nCols);
 
663
       }
 
664
        T trace = field.getZero();
 
665
        for (int i = 0; i < nRows; ++i) {
 
666
            trace = trace.add(getEntry(i, i));
 
667
        }
 
668
        return trace;
 
669
    }
 
670
 
 
671
    /** {@inheritDoc} */
 
672
    public T[] operate(final T[] v)
 
673
        throws IllegalArgumentException {
 
674
 
 
675
        final int nRows = getRowDimension();
 
676
        final int nCols = getColumnDimension();
 
677
        if (v.length != nCols) {
 
678
            throw MathRuntimeException.createIllegalArgumentException(
 
679
                    "vector length mismatch: got {0} but expected {1}",
 
680
                    v.length, nCols);
 
681
        }
 
682
 
 
683
        final T[] out = buildArray(field, nRows);
 
684
        for (int row = 0; row < nRows; ++row) {
 
685
            T sum = field.getZero();
 
686
            for (int i = 0; i < nCols; ++i) {
 
687
                sum = sum.add(getEntry(row, i).multiply(v[i]));
 
688
            }
 
689
            out[row] = sum;
 
690
        }
 
691
 
 
692
        return out;
 
693
 
 
694
    }
 
695
 
 
696
    /** {@inheritDoc} */
 
697
    public FieldVector<T> operate(final FieldVector<T> v)
 
698
        throws IllegalArgumentException {
 
699
        try {
 
700
            return new ArrayFieldVector<T>(operate(((ArrayFieldVector<T>) v).getDataRef()), false);
 
701
        } catch (ClassCastException cce) {
 
702
            final int nRows = getRowDimension();
 
703
            final int nCols = getColumnDimension();
 
704
            if (v.getDimension() != nCols) {
 
705
                throw MathRuntimeException.createIllegalArgumentException(
 
706
                        "vector length mismatch: got {0} but expected {1}",
 
707
                        v.getDimension(), nCols);
 
708
            }
 
709
 
 
710
            final T[] out = buildArray(field, nRows);
 
711
            for (int row = 0; row < nRows; ++row) {
 
712
                T sum = field.getZero();
 
713
                for (int i = 0; i < nCols; ++i) {
 
714
                    sum = sum.add(getEntry(row, i).multiply(v.getEntry(i)));
 
715
                }
 
716
                out[row] = sum;
 
717
            }
 
718
 
 
719
            return new ArrayFieldVector<T>(out, false);
 
720
        }
 
721
    }
 
722
 
 
723
    /** {@inheritDoc} */
 
724
    public T[] preMultiply(final T[] v)
 
725
        throws IllegalArgumentException {
 
726
 
 
727
        final int nRows = getRowDimension();
 
728
        final int nCols = getColumnDimension();
 
729
        if (v.length != nRows) {
 
730
            throw MathRuntimeException.createIllegalArgumentException(
 
731
                    "vector length mismatch: got {0} but expected {1}",
 
732
                    v.length, nRows);
 
733
        }
 
734
 
 
735
        final T[] out = buildArray(field, nCols);
 
736
        for (int col = 0; col < nCols; ++col) {
 
737
            T sum = field.getZero();
 
738
            for (int i = 0; i < nRows; ++i) {
 
739
                sum = sum.add(getEntry(i, col).multiply(v[i]));
 
740
            }
 
741
            out[col] = sum;
 
742
        }
 
743
 
 
744
        return out;
 
745
 
 
746
    }
 
747
 
 
748
    /** {@inheritDoc} */
 
749
    public FieldVector<T> preMultiply(final FieldVector<T> v)
 
750
        throws IllegalArgumentException {
 
751
        try {
 
752
            return new ArrayFieldVector<T>(preMultiply(((ArrayFieldVector<T>) v).getDataRef()), false);
 
753
        } catch (ClassCastException cce) {
 
754
 
 
755
            final int nRows = getRowDimension();
 
756
            final int nCols = getColumnDimension();
 
757
            if (v.getDimension() != nRows) {
 
758
                throw MathRuntimeException.createIllegalArgumentException(
 
759
                        "vector length mismatch: got {0} but expected {1}",
 
760
                        v.getDimension(), nRows);
 
761
            }
 
762
 
 
763
            final T[] out = buildArray(field, nCols);
 
764
            for (int col = 0; col < nCols; ++col) {
 
765
                T sum = field.getZero();
 
766
                for (int i = 0; i < nRows; ++i) {
 
767
                    sum = sum.add(getEntry(i, col).multiply(v.getEntry(i)));
 
768
                }
 
769
                out[col] = sum;
 
770
            }
 
771
 
 
772
            return new ArrayFieldVector<T>(out);
 
773
 
 
774
        }
 
775
    }
 
776
 
 
777
    /** {@inheritDoc} */
 
778
    public T walkInRowOrder(final FieldMatrixChangingVisitor<T> visitor)
 
779
        throws MatrixVisitorException {
 
780
        final int rows    = getRowDimension();
 
781
        final int columns = getColumnDimension();
 
782
        visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
 
783
        for (int row = 0; row < rows; ++row) {
 
784
            for (int column = 0; column < columns; ++column) {
 
785
                final T oldValue = getEntry(row, column);
 
786
                final T newValue = visitor.visit(row, column, oldValue);
 
787
                setEntry(row, column, newValue);
 
788
            }
 
789
        }
 
790
        return visitor.end();
 
791
    }
 
792
 
 
793
    /** {@inheritDoc} */
 
794
    public T walkInRowOrder(final FieldMatrixPreservingVisitor<T> visitor)
 
795
        throws MatrixVisitorException {
 
796
        final int rows    = getRowDimension();
 
797
        final int columns = getColumnDimension();
 
798
        visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
 
799
        for (int row = 0; row < rows; ++row) {
 
800
            for (int column = 0; column < columns; ++column) {
 
801
                visitor.visit(row, column, getEntry(row, column));
 
802
            }
 
803
        }
 
804
        return visitor.end();
 
805
    }
 
806
 
 
807
    /** {@inheritDoc} */
 
808
    public T walkInRowOrder(final FieldMatrixChangingVisitor<T> visitor,
 
809
                            final int startRow, final int endRow,
 
810
                            final int startColumn, final int endColumn)
 
811
        throws MatrixIndexException, MatrixVisitorException {
 
812
        checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
 
813
        visitor.start(getRowDimension(), getColumnDimension(),
 
814
                      startRow, endRow, startColumn, endColumn);
 
815
        for (int row = startRow; row <= endRow; ++row) {
 
816
            for (int column = startColumn; column <= endColumn; ++column) {
 
817
                final T oldValue = getEntry(row, column);
 
818
                final T newValue = visitor.visit(row, column, oldValue);
 
819
                setEntry(row, column, newValue);
 
820
            }
 
821
        }
 
822
        return visitor.end();
 
823
    }
 
824
 
 
825
    /** {@inheritDoc} */
 
826
    public T walkInRowOrder(final FieldMatrixPreservingVisitor<T> visitor,
 
827
                                 final int startRow, final int endRow,
 
828
                                 final int startColumn, final int endColumn)
 
829
        throws MatrixIndexException, MatrixVisitorException {
 
830
        checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
 
831
        visitor.start(getRowDimension(), getColumnDimension(),
 
832
                      startRow, endRow, startColumn, endColumn);
 
833
        for (int row = startRow; row <= endRow; ++row) {
 
834
            for (int column = startColumn; column <= endColumn; ++column) {
 
835
                visitor.visit(row, column, getEntry(row, column));
 
836
            }
 
837
        }
 
838
        return visitor.end();
 
839
    }
 
840
 
 
841
    /** {@inheritDoc} */
 
842
    public T walkInColumnOrder(final FieldMatrixChangingVisitor<T> visitor)
 
843
        throws MatrixVisitorException {
 
844
        final int rows    = getRowDimension();
 
845
        final int columns = getColumnDimension();
 
846
        visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
 
847
        for (int column = 0; column < columns; ++column) {
 
848
            for (int row = 0; row < rows; ++row) {
 
849
                final T oldValue = getEntry(row, column);
 
850
                final T newValue = visitor.visit(row, column, oldValue);
 
851
                setEntry(row, column, newValue);
 
852
            }
 
853
        }
 
854
        return visitor.end();
 
855
    }
 
856
 
 
857
    /** {@inheritDoc} */
 
858
    public T walkInColumnOrder(final FieldMatrixPreservingVisitor<T> visitor)
 
859
        throws MatrixVisitorException {
 
860
        final int rows    = getRowDimension();
 
861
        final int columns = getColumnDimension();
 
862
        visitor.start(rows, columns, 0, rows - 1, 0, columns - 1);
 
863
        for (int column = 0; column < columns; ++column) {
 
864
            for (int row = 0; row < rows; ++row) {
 
865
                visitor.visit(row, column, getEntry(row, column));
 
866
            }
 
867
        }
 
868
        return visitor.end();
 
869
    }
 
870
 
 
871
    /** {@inheritDoc} */
 
872
    public T walkInColumnOrder(final FieldMatrixChangingVisitor<T> visitor,
 
873
                               final int startRow, final int endRow,
 
874
                               final int startColumn, final int endColumn)
 
875
    throws MatrixIndexException, MatrixVisitorException {
 
876
        checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
 
877
        visitor.start(getRowDimension(), getColumnDimension(),
 
878
                      startRow, endRow, startColumn, endColumn);
 
879
        for (int column = startColumn; column <= endColumn; ++column) {
 
880
            for (int row = startRow; row <= endRow; ++row) {
 
881
                final T oldValue = getEntry(row, column);
 
882
                final T newValue = visitor.visit(row, column, oldValue);
 
883
                setEntry(row, column, newValue);
 
884
            }
 
885
        }
 
886
        return visitor.end();
 
887
    }
 
888
 
 
889
    /** {@inheritDoc} */
 
890
    public T walkInColumnOrder(final FieldMatrixPreservingVisitor<T> visitor,
 
891
                               final int startRow, final int endRow,
 
892
                               final int startColumn, final int endColumn)
 
893
    throws MatrixIndexException, MatrixVisitorException {
 
894
        checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
 
895
        visitor.start(getRowDimension(), getColumnDimension(),
 
896
                      startRow, endRow, startColumn, endColumn);
 
897
        for (int column = startColumn; column <= endColumn; ++column) {
 
898
            for (int row = startRow; row <= endRow; ++row) {
 
899
                visitor.visit(row, column, getEntry(row, column));
 
900
            }
 
901
        }
 
902
        return visitor.end();
 
903
    }
 
904
 
 
905
    /** {@inheritDoc} */
 
906
    public T walkInOptimizedOrder(final FieldMatrixChangingVisitor<T> visitor)
 
907
        throws MatrixVisitorException {
 
908
        return walkInRowOrder(visitor);
 
909
    }
 
910
 
 
911
    /** {@inheritDoc} */
 
912
    public T walkInOptimizedOrder(final FieldMatrixPreservingVisitor<T> visitor)
 
913
        throws MatrixVisitorException {
 
914
        return walkInRowOrder(visitor);
 
915
    }
 
916
 
 
917
    /** {@inheritDoc} */
 
918
    public T walkInOptimizedOrder(final FieldMatrixChangingVisitor<T> visitor,
 
919
                                       final int startRow, final int endRow,
 
920
                                       final int startColumn, final int endColumn)
 
921
        throws MatrixIndexException, MatrixVisitorException {
 
922
        return walkInRowOrder(visitor, startRow, endRow, startColumn, endColumn);
 
923
    }
 
924
 
 
925
    /** {@inheritDoc} */
 
926
    public T walkInOptimizedOrder(final FieldMatrixPreservingVisitor<T> visitor,
 
927
                                       final int startRow, final int endRow,
 
928
                                       final int startColumn, final int endColumn)
 
929
        throws MatrixIndexException, MatrixVisitorException {
 
930
        return walkInRowOrder(visitor, startRow, endRow, startColumn, endColumn);
 
931
    }
 
932
 
 
933
    /**
 
934
     * Get a string representation for this matrix.
 
935
     * @return a string representation for this matrix
 
936
     */
 
937
    @Override
 
938
    public String toString() {
 
939
        final int nRows = getRowDimension();
 
940
        final int nCols = getColumnDimension();
 
941
        final StringBuffer res = new StringBuffer();
 
942
        String fullClassName = getClass().getName();
 
943
        String shortClassName = fullClassName.substring(fullClassName.lastIndexOf('.') + 1);
 
944
        res.append(shortClassName).append("{");
 
945
 
 
946
        for (int i = 0; i < nRows; ++i) {
 
947
            if (i > 0) {
 
948
                res.append(",");
 
949
            }
 
950
            res.append("{");
 
951
            for (int j = 0; j < nCols; ++j) {
 
952
                if (j > 0) {
 
953
                    res.append(",");
 
954
                }
 
955
                res.append(getEntry(i, j));
 
956
            } 
 
957
            res.append("}");
 
958
        } 
 
959
 
 
960
        res.append("}");
 
961
        return res.toString();
 
962
 
 
963
    } 
 
964
    
 
965
    /**
 
966
     * Returns true iff <code>object</code> is a
 
967
     * <code>FieldMatrix</code> instance with the same dimensions as this
 
968
     * and all corresponding matrix entries are equal.
 
969
     * 
 
970
     * @param object the object to test equality against.
 
971
     * @return true if object equals this
 
972
     */
 
973
    @SuppressWarnings("unchecked")
 
974
    @Override
 
975
    public boolean equals(final Object object) {
 
976
        if (object == this ) {
 
977
            return true;
 
978
        }
 
979
        if (object instanceof FieldMatrix == false) {
 
980
            return false;
 
981
        }
 
982
        FieldMatrix<T> m = (FieldMatrix<T>) object;
 
983
        final int nRows = getRowDimension();
 
984
        final int nCols = getColumnDimension();
 
985
        if (m.getColumnDimension() != nCols || m.getRowDimension() != nRows) {
 
986
            return false;
 
987
        }
 
988
        for (int row = 0; row < nRows; ++row) {
 
989
            for (int col = 0; col < nCols; ++col) {
 
990
                if (!getEntry(row, col).equals(m.getEntry(row, col))) {
 
991
                    return false;
 
992
                }
 
993
            }
 
994
        }
 
995
        return true;
 
996
    }
 
997
    
 
998
    /**
 
999
     * Computes a hashcode for the matrix.
 
1000
     * 
 
1001
     * @return hashcode for matrix
 
1002
     */
 
1003
    @Override
 
1004
    public int hashCode() {
 
1005
        int ret = 322562;
 
1006
        final int nRows = getRowDimension();
 
1007
        final int nCols = getColumnDimension();
 
1008
        ret = ret * 31 + nRows;
 
1009
        ret = ret * 31 + nCols;
 
1010
        for (int row = 0; row < nRows; ++row) {
 
1011
            for (int col = 0; col < nCols; ++col) {
 
1012
               ret = ret * 31 + (11 * (row+1) + 17 * (col+1)) * getEntry(row, col).hashCode();
 
1013
           }
 
1014
        }
 
1015
        return ret;
 
1016
    }
 
1017
 
 
1018
    /**
 
1019
     * Check if a row index is valid.
 
1020
     * @param row row index to check
 
1021
     * @exception MatrixIndexException if index is not valid
 
1022
     */
 
1023
    protected void checkRowIndex(final int row) {
 
1024
        if (row < 0 || row >= getRowDimension()) {
 
1025
            throw new MatrixIndexException("row index {0} out of allowed range [{1}, {2}]",
 
1026
                                           row, 0, getRowDimension() - 1);
 
1027
        }
 
1028
    }
 
1029
 
 
1030
    /**
 
1031
     * Check if a column index is valid.
 
1032
     * @param column column index to check
 
1033
     * @exception MatrixIndexException if index is not valid
 
1034
     */
 
1035
    protected void checkColumnIndex(final int column)
 
1036
        throws MatrixIndexException {
 
1037
        if (column < 0 || column >= getColumnDimension()) {
 
1038
            throw new MatrixIndexException("column index {0} out of allowed range [{1}, {2}]",
 
1039
                                           column, 0, getColumnDimension() - 1);
 
1040
        }
 
1041
    }
 
1042
 
 
1043
    /**
 
1044
     * Check if submatrix ranges indices are valid.
 
1045
     * Rows and columns are indicated counting from 0 to n-1.
 
1046
     *
 
1047
     * @param startRow Initial row index
 
1048
     * @param endRow Final row index
 
1049
     * @param startColumn Initial column index
 
1050
     * @param endColumn Final column index
 
1051
     * @exception MatrixIndexException  if the indices are not valid
 
1052
     */
 
1053
    protected void checkSubMatrixIndex(final int startRow, final int endRow,
 
1054
                                       final int startColumn, final int endColumn) {
 
1055
        checkRowIndex(startRow);
 
1056
        checkRowIndex(endRow);
 
1057
        if (startRow > endRow) {
 
1058
            throw new MatrixIndexException("initial row {0} after final row {1}",
 
1059
                                           startRow, endRow);
 
1060
        }
 
1061
 
 
1062
        checkColumnIndex(startColumn);
 
1063
        checkColumnIndex(endColumn);
 
1064
        if (startColumn > endColumn) {
 
1065
            throw new MatrixIndexException("initial column {0} after final column {1}",
 
1066
                                           startColumn, endColumn);
 
1067
        }
 
1068
 
 
1069
    
 
1070
    }
 
1071
 
 
1072
    /**
 
1073
     * Check if submatrix ranges indices are valid.
 
1074
     * Rows and columns are indicated counting from 0 to n-1.
 
1075
     *
 
1076
     * @param selectedRows Array of row indices.
 
1077
     * @param selectedColumns Array of column indices.
 
1078
     * @exception MatrixIndexException if row or column selections are not valid
 
1079
     */
 
1080
    protected void checkSubMatrixIndex(final int[] selectedRows, final int[] selectedColumns) {
 
1081
        if (selectedRows.length * selectedColumns.length == 0) {
 
1082
            if (selectedRows.length == 0) {
 
1083
                throw new MatrixIndexException("empty selected row index array");
 
1084
            }
 
1085
            throw new MatrixIndexException("empty selected column index array");
 
1086
        }
 
1087
 
 
1088
        for (final int row : selectedRows) {
 
1089
            checkRowIndex(row);
 
1090
        }
 
1091
        for (final int column : selectedColumns) {
 
1092
            checkColumnIndex(column);
 
1093
        }
 
1094
    }
 
1095
 
 
1096
    /**
 
1097
     * Check if a matrix is addition compatible with the instance
 
1098
     * @param m matrix to check
 
1099
     * @exception IllegalArgumentException if matrix is not addition compatible with instance
 
1100
     */
 
1101
    protected void checkAdditionCompatible(final FieldMatrix<T> m) {
 
1102
        if ((getRowDimension()    != m.getRowDimension()) ||
 
1103
            (getColumnDimension() != m.getColumnDimension())) {
 
1104
            throw MathRuntimeException.createIllegalArgumentException(
 
1105
                    "{0}x{1} and {2}x{3} matrices are not addition compatible",
 
1106
                    getRowDimension(), getColumnDimension(),
 
1107
                    m.getRowDimension(), m.getColumnDimension());
 
1108
        }
 
1109
    }
 
1110
 
 
1111
    /**
 
1112
     * Check if a matrix is subtraction compatible with the instance
 
1113
     * @param m matrix to check
 
1114
     * @exception IllegalArgumentException if matrix is not subtraction compatible with instance
 
1115
     */
 
1116
    protected void checkSubtractionCompatible(final FieldMatrix<T> m) {
 
1117
        if ((getRowDimension()    != m.getRowDimension()) ||
 
1118
            (getColumnDimension() != m.getColumnDimension())) {
 
1119
            throw MathRuntimeException.createIllegalArgumentException(
 
1120
                    "{0}x{1} and {2}x{3} matrices are not subtraction compatible",
 
1121
                    getRowDimension(), getColumnDimension(),
 
1122
                    m.getRowDimension(), m.getColumnDimension());
 
1123
        }
 
1124
    }
 
1125
 
 
1126
    /**
 
1127
     * Check if a matrix is multiplication compatible with the instance
 
1128
     * @param m matrix to check
 
1129
     * @exception IllegalArgumentException if matrix is not multiplication compatible with instance
 
1130
     */
 
1131
    protected void checkMultiplicationCompatible(final FieldMatrix<T> m) {
 
1132
        if (getColumnDimension() != m.getRowDimension()) {
 
1133
            throw MathRuntimeException.createIllegalArgumentException(
 
1134
                    "{0}x{1} and {2}x{3} matrices are not multiplication compatible",
 
1135
                    getRowDimension(), getColumnDimension(),
 
1136
                    m.getRowDimension(), m.getColumnDimension());
 
1137
        }
 
1138
    }
 
1139
 
 
1140
}