001 /* 002 * Copyright (C) 2008-2010 by Holger Arndt 003 * 004 * This file is part of the Universal Java Matrix Package (UJMP). 005 * See the NOTICE file distributed with this work for additional 006 * information regarding copyright ownership and licensing. 007 * 008 * UJMP is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU Lesser General Public License as 010 * published by the Free Software Foundation; either version 2 011 * of the License, or (at your option) any later version. 012 * 013 * UJMP is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU Lesser General Public License for more details. 017 * 018 * You should have received a copy of the GNU Lesser General Public 019 * License along with UJMP; if not, write to the 020 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 021 * Boston, MA 02110-1301 USA 022 */ 023 024 package org.ujmp.jscience; 025 026 import java.io.IOException; 027 import java.io.ObjectInputStream; 028 import java.io.ObjectOutputStream; 029 030 import javolution.util.FastTable; 031 import javolution.util.Index; 032 033 import org.jscience.mathematics.number.Float64; 034 import org.jscience.mathematics.vector.DenseMatrix; 035 import org.jscience.mathematics.vector.Float64Matrix; 036 import org.jscience.mathematics.vector.Float64Vector; 037 import org.jscience.mathematics.vector.LUDecomposition; 038 import org.jscience.mathematics.vector.SparseMatrix; 039 import org.ujmp.core.Coordinates; 040 import org.ujmp.core.Matrix; 041 import org.ujmp.core.doublematrix.stub.AbstractDenseDoubleMatrix2D; 042 import org.ujmp.core.exceptions.MatrixException; 043 import org.ujmp.core.interfaces.Wrapper; 044 import org.ujmp.core.util.ReflectionUtil; 045 046 public class JScienceDenseDoubleMatrix2D extends AbstractDenseDoubleMatrix2D 047 implements Wrapper<Float64Matrix> { 048 private static final long serialVersionUID = -7874694468839411484L; 049 050 private transient Float64Matrix matrix = null; 051 052 private Boolean transposed = false; 053 054 private transient FastTable<Float64Vector> rows = null; 055 056 public JScienceDenseDoubleMatrix2D(long... size) { 057 if (Coordinates.product(size) != 0) { 058 this.matrix = Float64Matrix 059 .valueOf(new double[(int) size[ROW]][(int) size[COLUMN]]); 060 } 061 } 062 063 public JScienceDenseDoubleMatrix2D(Float64Matrix matrix) { 064 this.matrix = matrix; 065 } 066 067 public JScienceDenseDoubleMatrix2D(double[][] values) { 068 this.matrix = Float64Matrix.valueOf(values); 069 } 070 071 public JScienceDenseDoubleMatrix2D(double[] values) { 072 this.matrix = Float64Matrix.valueOf(Float64Vector.valueOf(values)); 073 } 074 075 public JScienceDenseDoubleMatrix2D(Matrix matrix) throws MatrixException { 076 this.matrix = Float64Matrix.valueOf(matrix.toDoubleArray()); 077 } 078 079 public JScienceDenseDoubleMatrix2D(DenseMatrix<Float64> matrix) { 080 this.matrix = Float64Matrix.valueOf(matrix); 081 } 082 083 public JScienceDenseDoubleMatrix2D(SparseMatrix<Float64> matrix) { 084 this.matrix = Float64Matrix.valueOf(matrix); 085 } 086 087 public double getDouble(long row, long column) { 088 return matrix.get((int) row, (int) column).doubleValue(); 089 } 090 091 public double getDouble(int row, int column) { 092 return matrix.get(row, column).doubleValue(); 093 } 094 095 public long[] getSize() { 096 return matrix == null ? Coordinates.ZERO2D : new long[] { 097 matrix.getNumberOfRows(), matrix.getNumberOfColumns() }; 098 } 099 100 public void setDouble(double value, long row, long column) { 101 if (getTransposed()) { 102 Float64Vector f = getRowsTable().get((int) column); 103 double[] data = (double[]) ReflectionUtil.extractPrivateField(f, 104 "_values"); 105 data[(int) row] = value; 106 } else { 107 Float64Vector f = getRowsTable().get((int) row); 108 double[] data = (double[]) ReflectionUtil.extractPrivateField(f, 109 "_values"); 110 data[(int) column] = value; 111 } 112 } 113 114 private boolean getTransposed() { 115 if (transposed == null) { 116 transposed = (Boolean) ReflectionUtil.extractPrivateField( 117 Float64Matrix.class, matrix, "_transposed"); 118 } 119 return transposed; 120 } 121 122 @SuppressWarnings("unchecked") 123 private FastTable<Float64Vector> getRowsTable() { 124 if (rows == null) { 125 rows = (FastTable<Float64Vector>) ReflectionUtil 126 .extractPrivateField(Float64Matrix.class, matrix, "_rows"); 127 } 128 return rows; 129 } 130 131 public void setDouble(double value, int row, int column) { 132 if (getTransposed()) { 133 Float64Vector f = getRowsTable().get(column); 134 double[] data = (double[]) ReflectionUtil.extractPrivateField( 135 Float64Vector.class, f, "_values"); 136 data[row] = value; 137 } else { 138 Float64Vector f = getRowsTable().get(row); 139 double[] data = (double[]) ReflectionUtil.extractPrivateField( 140 Float64Vector.class, f, "_values"); 141 data[column] = value; 142 } 143 } 144 145 public Matrix mtimes(Matrix that) { 146 if (that instanceof JScienceDenseDoubleMatrix2D) { 147 return new JScienceDenseDoubleMatrix2D(matrix 148 .times(((JScienceDenseDoubleMatrix2D) that).matrix)); 149 } else { 150 return super.mtimes(that); 151 } 152 } 153 154 public Matrix plus(Matrix that) { 155 if (that instanceof JScienceDenseDoubleMatrix2D) { 156 return new JScienceDenseDoubleMatrix2D(matrix 157 .plus(((JScienceDenseDoubleMatrix2D) that).matrix)); 158 } else { 159 return super.plus(that); 160 } 161 } 162 163 public Matrix minus(Matrix that) { 164 if (that instanceof JScienceDenseDoubleMatrix2D) { 165 return new JScienceDenseDoubleMatrix2D(matrix 166 .minus(((JScienceDenseDoubleMatrix2D) that).matrix)); 167 } else { 168 return super.minus(that); 169 } 170 } 171 172 public Matrix times(double value) { 173 return new JScienceDenseDoubleMatrix2D(matrix.times(Float64 174 .valueOf(value))); 175 } 176 177 public Matrix divide(double value) { 178 return new JScienceDenseDoubleMatrix2D(matrix.times(Float64 179 .valueOf(1.0 / value))); 180 } 181 182 public Matrix transpose() { 183 return new JScienceDenseDoubleMatrix2D(matrix.transpose().copy()); 184 } 185 186 public Matrix inv() { 187 return new JScienceDenseDoubleMatrix2D(matrix.inverse()); 188 } 189 190 public Matrix[] lu() { 191 if (isSquare()) { 192 LUDecomposition<Float64> lu = LUDecomposition.valueOf(matrix); 193 int m = (int) getRowCount(); 194 DenseMatrix<Float64> lt = lu.getLower(Float64.ZERO, Float64.ONE); 195 DenseMatrix<Float64> ut = lu.getUpper(Float64.ZERO); 196 FastTable<Index> piv = lu.getPivots(); 197 Matrix l = new JScienceDenseDoubleMatrix2D(lt); 198 Matrix u = new JScienceDenseDoubleMatrix2D(ut); 199 Matrix p = new JScienceDenseDoubleMatrix2D(m, m); 200 for (int i = 0; i < m; i++) { 201 p.setAsDouble(1, i, piv.get(i).intValue()); 202 } 203 return new Matrix[] { l, u, p }; 204 } else { 205 throw new MatrixException("matrix must be square"); 206 } 207 } 208 209 public Float64Matrix getWrappedObject() { 210 return matrix; 211 } 212 213 public void setWrappedObject(Float64Matrix object) { 214 this.matrix = object; 215 } 216 217 private void readObject(ObjectInputStream s) throws IOException, 218 ClassNotFoundException { 219 s.defaultReadObject(); 220 double[][] values = (double[][]) s.readObject(); 221 matrix = Float64Matrix.valueOf(values); 222 } 223 224 private void writeObject(ObjectOutputStream s) throws IOException, 225 MatrixException { 226 s.defaultWriteObject(); 227 s.writeObject(this.toDoubleArray()); 228 } 229 230 public Matrix solve(Matrix b) { 231 if (b instanceof JScienceDenseDoubleMatrix2D) { 232 JScienceDenseDoubleMatrix2D b2 = (JScienceDenseDoubleMatrix2D) b; 233 Float64Matrix x = Float64Matrix.valueOf(matrix.solve(b2.matrix)); 234 return new JScienceDenseDoubleMatrix2D(x); 235 } else { 236 return super.solve(b); 237 } 238 } 239 }