1 9 package org.jscience.mathematics.vectors; 10 11 import java.util.Iterator ; 12 import java.util.List ; 13 14 import javolution.context.ConcurrentContext; 15 import javolution.lang.MathLib; 16 import javolution.util.FastTable; 17 import javolution.util.Index; 18 19 import org.jscience.mathematics.numbers.Float64; 20 21 35 public final class Float64Matrix extends Matrix<Float64> { 36 37 40 int _n;; 41 42 45 boolean _transposed; 46 47 50 final FastTable<Float64Vector> _rows = new FastTable<Float64Vector>(); 51 52 62 public static Float64Matrix valueOf(double[][] values) { 63 int m = values.length; 64 int n = values[0].length; 65 Float64Matrix M = Float64Matrix.newInstance(n, false); 66 for (int i = 0; i < m; i++) { 67 Float64Vector row = Float64Vector.valueOf(values[i]); 68 if (row.getDimension() != n) 69 throw new DimensionException(); 70 M._rows.add(row); 71 } 72 return M; 73 } 74 75 83 public static Float64Matrix valueOf(Float64Vector... rows) { 84 final int n = rows[0].getDimension(); 85 Float64Matrix M = Float64Matrix.newInstance(n, false); 86 for (int i = 0, m = rows.length; i < m; i++) { 87 Float64Vector rowi = rows[i]; 88 if (rowi.getDimension() != n) 89 throw new DimensionException( 90 "All vectors must have the same dimension."); 91 M._rows.add(rowi); 92 } 93 return M; 94 } 95 96 104 public static Float64Matrix valueOf(List <Float64Vector> rows) { 105 final int n = rows.get(0).getDimension(); 106 Float64Matrix M = Float64Matrix.newInstance(n, false); 107 Iterator <Float64Vector> iterator = rows.iterator(); 108 for (int i = 0, m = rows.size(); i < m; i++) { 109 Float64Vector rowi = iterator.next(); 110 if (rowi.getDimension() != n) 111 throw new DimensionException( 112 "All vectors must have the same dimension."); 113 M._rows.add(rowi); 114 } 115 return M; 116 } 117 118 125 public static Float64Matrix valueOf(Matrix<Float64> that) { 126 if (that instanceof Float64Matrix) return (Float64Matrix)that; 127 int n = that.getNumberOfColumns(); 128 int m = that.getNumberOfRows(); 129 Float64Matrix M = Float64Matrix.newInstance(n, false); 130 for (int i = 0; i < m; i++) { 131 Float64Vector rowi = Float64Vector.valueOf(that.getRow(i)); 132 M._rows.add(rowi); 133 } 134 return M; 135 } 136 137 @Override 138 public int getNumberOfRows() { 139 return _transposed ? _n : _rows.size(); 140 } 141 142 @Override 143 public int getNumberOfColumns() { 144 return _transposed ? _rows.size() : _n; 145 } 146 147 @Override 148 public Float64 get(int i, int j) { 149 return _transposed ? _rows.get(j).get(i) : _rows.get(i).get(j); 150 } 151 152 @Override 153 public Float64Vector getRow(int i) { 154 if (!_transposed) return _rows.get(i); 155 int n = _rows.size(); 157 int m = _n; 158 if ((i < 0) || (i >= m)) throw new DimensionException(); 159 Float64Vector V = Float64Vector.newInstance(n); 160 for (int j=0; j < n; j++) { 161 V.set(j, _rows.get(j).get(i)); 162 } 163 return V; 164 } 165 166 @Override 167 public Float64Vector getColumn(int j) { 168 if (_transposed) return _rows.get(j); 169 int m = _rows.size(); 170 if ((j < 0) || (j >= _n)) throw new DimensionException(); 171 Float64Vector V = Float64Vector.newInstance(m); 172 for (int i=0; i < m; i++) { 173 V.set(i, _rows.get(i).get(j)); 174 } 175 return V; 176 } 177 178 @Override 179 public Float64Vector getDiagonal() { 180 int m = this.getNumberOfRows(); 181 int n = this.getNumberOfColumns(); 182 int dimension = MathLib.min(m, n); 183 Float64Vector V = Float64Vector.newInstance(dimension); 184 for (int i=0; i < dimension; i++) { 185 V.set(i, this.get(i, i)); 186 } 187 return V; 188 } 189 190 @Override 191 public Float64Matrix opposite() { 192 Float64Matrix M = Float64Matrix.newInstance(_n, _transposed); 193 for (int i = 0, p = _rows.size(); i < p; i++) { 194 M._rows.add(_rows.get(i).opposite()); 195 } 196 return M; 197 } 198 199 @Override 200 public Float64Matrix plus(Matrix<Float64> that) { 201 if (this.getNumberOfRows() != that.getNumberOfRows()) 202 throw new DimensionException(); 203 Float64Matrix M = Float64Matrix.newInstance(_n, _transposed); 204 for (int i = 0, p = _rows.size(); i < p; i++) { 205 M._rows.add(_rows.get(i).plus(_transposed ? that.getColumn(i) : that.getRow(i))); 206 } 207 return M; 208 } 209 210 @Override 211 public Float64Matrix minus(Matrix<Float64> that) { return this.plus(that.opposite()); 213 } 214 215 @Override 216 public Float64Matrix times(Float64 k) { 217 Float64Matrix M = Float64Matrix.newInstance(_n, _transposed); 218 for (int i = 0, p = _rows.size(); i < p; i++) { 219 M._rows.add(_rows.get(i).times(k)); 220 } 221 return M; 222 } 223 224 @Override 225 public Float64Vector times(Vector<Float64> v) { 226 if (v.getDimension() != this.getNumberOfColumns()) 227 throw new DimensionException(); 228 final int m = this.getNumberOfRows(); 229 Float64Vector V = Float64Vector.newInstance(m); 230 for (int i = 0; i < m; i++) { 231 V.set(i, this.getRow(i).times(v)); 232 } 233 return V; 234 } 235 236 @Override 237 public Float64Matrix times(Matrix<Float64> that) { 238 if (_transposed) return this.transpose().inverse().transpose(); 240 final int m = this.getNumberOfRows(); 242 final int p = that.getNumberOfColumns(); 243 if (that.getNumberOfRows() != _n) 244 throw new DimensionException(); 245 Float64Matrix M = Float64Matrix.newInstance(m, true); multiply(that, Index.valueOf(0), Index.valueOf(p), M._rows); 248 return M; 249 } 250 251 private void multiply( 253 Matrix<Float64> that, Index startColumn, Index endColumn, FastTable<Float64Vector> columnsResult) { 254 final int start = startColumn.intValue(); 255 final int end = endColumn.intValue(); 256 if (end - start < 32) { final int m = this._rows.size(); 258 for (int j = start; j < end; j++) { 259 Vector<Float64> thatColj = that.getColumn(j); 260 Float64Vector column = Float64Vector.newInstance(m); 261 columnsResult.add(column); 262 for (int i = 0; i < m; i++) { 263 Float64Vector thisRowi = this.getRow(i); 264 column.set(i, thisRowi.times(thatColj)); 265 } 266 } 267 } else { FastTable<Float64Vector> r1 = FastTable.newInstance(); 269 FastTable<Float64Vector> r2 = FastTable.newInstance(); 270 Index half = Index.valueOf((start + end) >> 1); 271 ConcurrentContext.enter(); 272 try { 273 ConcurrentContext.execute(MULTIPLY, this, that, startColumn, half, r1); 274 ConcurrentContext.execute(MULTIPLY, this, that, half, endColumn, r2); 275 } finally { 276 ConcurrentContext.exit(); 277 } 278 columnsResult.addAll(r1); 279 columnsResult.addAll(r2); 280 FastTable.recycle(r1); 281 FastTable.recycle(r2); 282 } 283 } 284 private static ConcurrentContext.Logic MULTIPLY = new ConcurrentContext.Logic() { 285 @SuppressWarnings ("unchecked") 286 public void run() { 287 Float64Matrix _this = getArgument(0); 288 Matrix _that = getArgument(1); 289 Index _startColumn = getArgument(2); 290 Index _endColumn = getArgument(3); 291 FastTable _columnsResult = getArgument(4); 292 _this.multiply(_that, _startColumn, _endColumn, _columnsResult); 293 } 294 }; 295 296 297 @Override 298 public Float64Matrix inverse() { 299 if (!isSquare()) 300 throw new DimensionException("Matrix not square"); 301 return Float64Matrix.valueOf(LUDecomposition.valueOf(this).inverse()); 302 } 303 304 @Override 305 public Float64 determinant() { 306 return LUDecomposition.valueOf(this).determinant(); 307 } 308 309 @Override 310 public Float64Matrix transpose() { 311 Float64Matrix M = Float64Matrix.newInstance(_n, !_transposed); 312 M._rows.addAll(this._rows); 313 return M; 314 } 315 316 @Override 317 public Float64 cofactor(int i, int j) { 318 if (_transposed) { 319 int k = i; i = j; j = k; } 321 int m = _rows.size(); 322 Float64Matrix M = Float64Matrix.newInstance(m - 1, _transposed); 323 for (int k1=0; k1 < m; k1++) { 324 if (k1 == i) continue; 325 Float64Vector row = _rows.get(k1); 326 Float64Vector V = Float64Vector.newInstance(_n - 1); 327 M._rows.add(V); 328 for (int k2=0, k=0; k2 < _n; k2++) { 329 if (k2 == j) continue; 330 V.set(k++, row.get(k2)); 331 } 332 } 333 return M.determinant(); 334 } 335 336 @Override 337 public Float64Matrix adjoint() { 338 Float64Matrix M = Float64Matrix.newInstance(_n, _transposed); 339 int m = _rows.size(); 340 for (int i = 0; i < m; i++) { 341 Float64Vector row = Float64Vector.newInstance(_n); 342 M._rows.add(row); 343 for (int j = 0; j < _n; j++) { 344 Float64 cofactor = _transposed ? cofactor(j, i) : cofactor(i, j); 345 row.set(j, ((i + j) % 2 == 0) ? cofactor : cofactor.opposite()); 346 } 347 } 348 return M.transpose(); 349 } 350 351 @Override 352 public Float64Matrix tensor(Matrix<Float64> that) { 353 return Float64Matrix.valueOf(DenseMatrix.valueOf(this).tensor(that)); 354 } 355 356 @Override 357 public Float64Vector vectorization() { 358 return Float64Vector.valueOf(DenseMatrix.valueOf(this).vectorization()); 359 } 360 361 @Override 362 public boolean move(ObjectSpace os) { 363 if (super.move(os)) { 364 for (int i=0, n=_rows.size(); i < n; i++) { 369 _rows.get(i).move(os); 370 } 371 return true; 372 } 373 return false; 374 } 375 376 380 static Float64Matrix newInstance(int n, boolean transposed) { 381 Float64Matrix M = FACTORY.object(); 382 M._n = n; 383 M._transposed = transposed; 384 return M; 385 } 386 387 private static Factory<Float64Matrix> FACTORY = new Factory<Float64Matrix>() { 388 @Override 389 protected Float64Matrix create() { 390 return new Float64Matrix(); 391 } 392 @Override 393 protected void cleanup(Float64Matrix matrix) { 394 matrix._rows.reset(); 395 } 396 }; 397 398 private Float64Matrix() { 399 } 400 401 private static final long serialVersionUID = 1L; 402 403 } | Popular Tags |