~seh999/jcog/proto3

« back to all changes in this revision

Viewing changes to spacetime/src/opencog/math/Matrix.java

  • Committer: SeH
  • Date: 2009-09-19 22:59:48 UTC
  • Revision ID: seh999@gmail.com-20090919225948-q3ab80xa57i74mm6
start of major jReality refactoring

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 *
 
3
 * This file is part of jReality. jReality is open source software, made
 
4
 * available under a BSD license:
 
5
 *
 
6
 * Copyright (c) 2003-2006, jReality Group: Charles Gunn, Tim Hoffmann, Markus
 
7
 * Schmies, Steffen Weissmann.
 
8
 *
 
9
 * All rights reserved.
 
10
 *
 
11
 * Redistribution and use in source and binary forms, with or without
 
12
 * modification, are permitted provided that the following conditions are met:
 
13
 *
 
14
 * - Redistributions of source code must retain the above copyright notice, this
 
15
 *   list of conditions and the following disclaimer.
 
16
 *
 
17
 * - Redistributions in binary form must reproduce the above copyright notice,
 
18
 *   this list of conditions and the following disclaimer in the documentation
 
19
 *   and/or other materials provided with the distribution.
 
20
 *
 
21
 * - Neither the name of jReality nor the names of its contributors nor the
 
22
 *   names of their associated organizations may be used to endorse or promote
 
23
 *   products derived from this software without specific prior written
 
24
 *   permission.
 
25
 *
 
26
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
27
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
28
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
29
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 
30
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
31
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
32
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
33
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
34
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
35
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
36
 * POSSIBILITY OF SUCH DAMAGE.
 
37
 *
 
38
 */
 
39
 
 
40
 
 
41
package opencog.math;
 
42
 
 
43
import java.io.Serializable;
 
44
 
 
45
import opencog.spacetime.space.SpaceComponent;
 
46
import opencog.spacetime.space.Transformation;
 
47
import opencog.spacetime.space.data.DoubleArray;
 
48
 
 
49
 
 
50
/**
 
51
 * A simple wrapper class for 4x4 real matrices.  The matrix is represented as a
 
52
 * linear array of 16 values (<tt>double[16]</tt> in order to avoid problems with Java's
 
53
 * multi-dimensional arrays. The elements are listed in row/column order and act on column vectors
 
54
 * sitting to the right of the matrix.
 
55
 * </p>
 
56
 * <p>
 
57
 * This class is not supposed to be a replacement for a full-fledged mathematical
 
58
 * package. It provides a convenient wrapper for double arrays that offers some basic
 
59
 * functionality for multiplying and inverting matrices and such, but if you want to
 
60
 * do more involved stuff, you probably want to use a dedicated math library.
 
61
 * 
 
62
 * @see opencog.math.Rn
 
63
 * @see opencog.math.P3
 
64
 * @see opencog.math.Pn
 
65
 * @author weissman
 
66
 *
 
67
 **/
 
68
public class Matrix implements Serializable {
 
69
  
 
70
        public final static double TOLERANCE = Rn.TOLERANCE;
 
71
        protected double[] matrix;
 
72
          
 
73
        
 
74
        public Matrix() {
 
75
                this(Rn.setIdentityMatrix(new double[16]));
 
76
        }
 
77
 
 
78
        /**
 
79
         * copy constructor
 
80
         * @param T
 
81
         */
 
82
        public Matrix(Matrix T) {
 
83
                matrix = new double[16];
 
84
                System.arraycopy(T.matrix, 0, matrix, 0, 16);
 
85
        }
 
86
 
 
87
    /**
 
88
     * plain wrapper for the array m; does NOT make a copy of m!
 
89
     * @param m the double array to be wrapped by this Matrix
 
90
     */
 
91
    public Matrix(double[] m) {
 
92
        if (m == null)
 
93
            m = Rn.setIdentityMatrix(new double[16]);
 
94
        if (m.length != 16)
 
95
            throw new IllegalArgumentException(
 
96
                    "invalid dimension for 4x4 matrix");
 
97
        matrix = m;
 
98
    }
 
99
    /**
 
100
     * TODO
 
101
     */
 
102
    public Matrix(double x00, double x01, double x02, double x03, double x10,
 
103
      double x11, double x12, double x13, double x20, double x21, double x22,
 
104
      double x23, double x30, double x31, double x32, double x33) {
 
105
    this(new double[] { x00, x01, x02, x03, x10, x11, x12, x13, x20, x21, x22,
 
106
        x23, x30, x31, x32, x33 });
 
107
  }
 
108
 
 
109
    /**
 
110
     * this constructor copies the content of the given DoubleArray. Note: the
 
111
     * given DoubleArray must have length == 16
 
112
     * 
 
113
     * @param the
 
114
     *          DoubleArray to copy and wrap
 
115
     */
 
116
    public Matrix(DoubleArray data) {
 
117
        this(data.toDoubleArray(null));
 
118
    }
 
119
 
 
120
    /**
 
121
     * this constructor copies the content of the given Transformation.
 
122
     * @param the Transformation to copy and wrap
 
123
     */
 
124
    public Matrix(Transformation data) {
 
125
        this(data == null ? null : data.getMatrix());
 
126
    }
 
127
 
 
128
        /**
 
129
         * @param A
 
130
         * @param B
 
131
         * @return A*B
 
132
         */
 
133
        public static Matrix times(Matrix A, Matrix B) {
 
134
                return new Matrix(Rn.times(null, A.matrix, B.matrix));
 
135
        }
 
136
 
 
137
        /**
 
138
         * @param A
 
139
         * @param B
 
140
         * @return A+B
 
141
         */
 
142
        public static Matrix sum(Matrix A, Matrix B) {
 
143
                return new Matrix(Rn.add(null, A.matrix, B.matrix));
 
144
        }
 
145
 
 
146
        /**
 
147
         * 
 
148
         * @param A
 
149
         * @param B
 
150
         * @return B * A * B^-1
 
151
         */
 
152
        public static Matrix conjugate(Matrix A, Matrix B) {
 
153
                return new Matrix(Rn.conjugateByMatrix(null, A.matrix, B.matrix));
 
154
        }
 
155
 
 
156
  /**
 
157
   * this flag is kept for extending classes, that need to know
 
158
   * whether the matrix aray was changed. It's their responsibility
 
159
   * to reset this flag.
 
160
   */
 
161
  protected transient boolean matrixChanged=true;
 
162
 
 
163
        /**
 
164
         * copies initValue
 
165
         * @param initValue
 
166
         */
 
167
        public void assignFrom(double[] initValue) {
 
168
    matrixChanged = true;
 
169
                System.arraycopy(initValue, 0, matrix, 0, 16);
 
170
        }
 
171
 
 
172
        /**
 
173
         * copies initValue
 
174
         * @param initValue
 
175
         */
 
176
        public void assignFrom(Matrix initValue) {
 
177
    matrixChanged = true;
 
178
                System.arraycopy(initValue.matrix, 0, matrix, 0, 16);
 
179
        }
 
180
        
 
181
  /**
 
182
   * copies initValue
 
183
   * @param initValue
 
184
   */
 
185
        public void assignFrom(DoubleArray data) {
 
186
        matrixChanged = true;
 
187
        if (data.getLength() != 16)
 
188
                        throw new IllegalArgumentException(
 
189
                                        "invalid dimension for 4x4 matrix");
 
190
                data.toDoubleArray(matrix);
 
191
        }
 
192
 
 
193
  /**
 
194
   * copies initValue
 
195
   * @param initValue
 
196
   */
 
197
  public void assignFrom(Transformation trafo) {
 
198
    matrixChanged = true;
 
199
    trafo.getMatrix(matrix);
 
200
  }
 
201
  
 
202
  /**
 
203
   * TODO: assign single values!
 
204
   */
 
205
  public void assignFrom(double x00, double x01, double x02, double x03, double x10,
 
206
      double x11, double x12, double x13, double x20, double x21, double x22,
 
207
      double x23, double x30, double x31, double x32, double x33) {
 
208
    assignFrom(new double[] { x00, x01, x02, x03, x10, x11, x12, x13, x20, x21, x22,
 
209
        x23, x30, x31, x32, x33 });
 
210
  }
 
211
 
 
212
 
 
213
  public void assignTo(double[] array) {
 
214
    System.arraycopy(matrix, 0, array, 0, 16);
 
215
  }
 
216
  
 
217
  public void assignTo(Matrix m) {
 
218
    m.assignFrom(matrix);
 
219
  }
 
220
  
 
221
  public void assignTo(Transformation trafo) {
 
222
    trafo.setMatrix(matrix);
 
223
  }
 
224
 
 
225
  /**
 
226
   * Set the matrix of the transformation of <i>comp</i> to be this instance.  If <i>comp</i> has 
 
227
   * no Transformation, create one.
 
228
   * @param comp
 
229
   */public void assignTo(SpaceComponent comp) {
 
230
    Transformation t = comp.getTransformation();
 
231
    if (t == null) comp.setTransformation(new Transformation());
 
232
    assignTo(comp.getTransformation());
 
233
  }
 
234
 
 
235
        public void assignIdentity() {
 
236
    matrixChanged = true;
 
237
                Rn.setIdentityMatrix(matrix);
 
238
        }
 
239
 
 
240
        public double getDeterminant() {
 
241
                return Rn.determinant(matrix);
 
242
        }
 
243
 
 
244
        public double getTrace() {
 
245
                return Rn.trace(matrix);
 
246
        }
 
247
 
 
248
        public double getEntry(int row, int column) {
 
249
                return matrix[4 * row + column];
 
250
        }
 
251
 
 
252
        public void setEntry(int row, int column, double value) {
 
253
    if (matrix[4 * row + column] != value) matrixChanged = true;
 
254
                matrix[4 * row + column] = value;
 
255
        }
 
256
 
 
257
        public double[] getRow(int i) {
 
258
                return new double[] { matrix[4 * i], matrix[4 * i + 1],
 
259
                                matrix[4 * i + 2], matrix[4 * i + 3] };
 
260
        }
 
261
 
 
262
        public void setRow(int i, double[] v) {
 
263
    matrixChanged = true;
 
264
    matrix[4 * i] = v[0];
 
265
                matrix[4 * i + 1] = v[1];
 
266
                matrix[4 * i + 2] = v[2];
 
267
                matrix[4 * i + 3] = v[3];
 
268
        }
 
269
 
 
270
        public double[] getColumn(int i) {
 
271
                return new double[] { matrix[i], matrix[i + 4], matrix[i + 8],
 
272
                                matrix[i + 12] };
 
273
        }
 
274
 
 
275
  /**
 
276
   * assigns the values of the ith column with the values from v.
 
277
   * if v.length == 3, then the 4th entry of the column is set to 0.
 
278
   * @param i
 
279
   * @param v
 
280
   */
 
281
        public void setColumn(int i, double[] v) {
 
282
    matrixChanged = true;
 
283
                matrix[i] = v[0];
 
284
                matrix[i + 4] = v[1];
 
285
                matrix[i + 8] = v[2];
 
286
                matrix[i + 12] = (v.length > 3) ? v[3] : 0;
 
287
        }
 
288
    
 
289
        /**
 
290
         * 
 
291
         * @return reference to the current matrix
 
292
         */
 
293
        public double[] getArray() {
 
294
                return matrix;
 
295
        }
 
296
 
 
297
        /**
 
298
         * Copy the current matrix into <i>aMatrix</i> and return it.
 
299
         * @param aMatrix
 
300
         * @return  the filled in matrix
 
301
         */
 
302
        public double[] writeToArray(double[] aMatrix) {
 
303
                if (aMatrix != null && aMatrix.length != 16)
 
304
                        throw new IllegalArgumentException("matrix must have length 16");
 
305
                double[] copy = aMatrix == null ? new double[16] : aMatrix;
 
306
                System.arraycopy(matrix, 0, copy, 0, 16);
 
307
                return copy;
 
308
        }
 
309
 
 
310
        /**
 
311
         * Let M be the current matrix. Then form the matrix product M*T and store it in M.
 
312
         * 
 
313
         * @param aMatrix
 
314
         */
 
315
        public void multiplyOnRight(double[] T) {
 
316
    matrixChanged = true;
 
317
                Rn.times(matrix, matrix, T);
 
318
        }
 
319
 
 
320
        /**
 
321
         * Let M be the current matrix. Then form the matrix product M*T and store it in M.
 
322
         * 
 
323
         * @param aMatrix
 
324
         */
 
325
        public void multiplyOnRight(Matrix T) {
 
326
                multiplyOnRight(T.matrix);
 
327
        }
 
328
 
 
329
        /**
 
330
         * Let M be the current matrix. Then form the matrix product T*M and store it in M.
 
331
         * @param aMatrix
 
332
         */
 
333
        public void multiplyOnLeft(double[] T) {
 
334
    matrixChanged = true;
 
335
                Rn.times(matrix, T, matrix);
 
336
        }
 
337
 
 
338
        /**
 
339
         * Let M be the current matrix. Then form the matrix product T*M and store it in M.
 
340
         * @param aMatrix
 
341
         */
 
342
        public void multiplyOnLeft(Matrix T) {
 
343
                multiplyOnLeft(T.matrix);
 
344
        }
 
345
 
 
346
        /**
 
347
         * Let M be the current Matrix.
 
348
         * 
 
349
         * assigns T * M * T^-1 
 
350
         * 
 
351
         * @param T
 
352
         */
 
353
        public void conjugateBy(Matrix T) {
 
354
                matrixChanged = true;
 
355
                Rn.conjugateByMatrix(matrix, matrix, T.matrix);
 
356
        }
 
357
 
 
358
        /**
 
359
         * Let M be the current Matrix.
 
360
         * 
 
361
         * assigns M + T 
 
362
         * 
 
363
         * @param T the matrix to add
 
364
         */
 
365
        public void add(Matrix T) {
 
366
                matrixChanged = true;
 
367
                Rn.add(matrix, matrix, T.matrix);
 
368
        }
 
369
 
 
370
        /**
 
371
         * Let M be the current Matrix.
 
372
         * 
 
373
         * assigns M - T 
 
374
         * 
 
375
         * @param T the matrix to subtract
 
376
         */
 
377
        public void subtract(Matrix T) {
 
378
                matrixChanged = true;
 
379
                Rn.subtract(matrix, matrix, T.matrix);
 
380
        }
 
381
 
 
382
        /**
 
383
         * Let M be the current Matrix.
 
384
         * 
 
385
         * assigns f * M 
 
386
         * 
 
387
         * @param f the scalar to multiply M with
 
388
         */
 
389
        public void times(double f) {
 
390
                matrixChanged = true;
 
391
                Rn.times(matrix, f, matrix);
 
392
        }
 
393
        
 
394
        public Matrix getInverse() {
 
395
                return new Matrix(Rn.inverse(null, matrix));
 
396
        }
 
397
 
 
398
        public void invert() {
 
399
    matrixChanged = true;
 
400
                Rn.inverse(matrix, matrix);
 
401
        }
 
402
 
 
403
        public Matrix getTranspose() {
 
404
                return new Matrix(Rn.transpose(null, matrix));
 
405
        }
 
406
 
 
407
        public void transpose() {
 
408
                matrixChanged = true;
 
409
                Rn.transpose(matrix, matrix);
 
410
        }
 
411
 
 
412
    /**
 
413
     * Form the matrix-vector product <i>M.v</i> (<i>v</i> is column vector on the right).
 
414
     * @param v the vector v
 
415
     * @return M.v
 
416
     */public double[] multiplyVector(double[] v) {
 
417
        return Rn.matrixTimesVector(null, matrix, v);
 
418
    }
 
419
    
 
420
     /**
 
421
      * Form the matrix-vector product <i>M.v</i> (<i>v</i> is column vector on the right) and assign it to v.
 
422
      * @param vector the vector to transform
 
423
      */public void transformVector(double[] v) {
 
424
         Rn.matrixTimesVector(v, matrix, v);
 
425
     }
 
426
     
 
427
  public boolean equals(Matrix T) {
 
428
                return Rn.equals(matrix, T.matrix);
 
429
        }
 
430
 
 
431
  public String toString() {
 
432
    return Rn.matrixToString(matrix);
 
433
  }
 
434
  
 
435
  public boolean containsNanOrInfinite() {
 
436
          for (double v : matrix) if (Double.isNaN(v) || Double.isInfinite(v)) return true;
 
437
          return false;
 
438
  }
 
439
 
 
440
}
 
 
b'\\ No newline at end of file'