001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.openimaj.math.matrix; 031 032import java.io.DataInput; 033import java.io.DataOutput; 034import java.io.IOException; 035import java.io.PrintWriter; 036import java.lang.reflect.Field; 037import java.util.Scanner; 038 039import org.openimaj.io.ReadWriteable; 040 041import Jama.Matrix; 042 043/** 044 * A wrapper around a JAMA Matrix that is read-writeable by 045 * OpenIMAJ IOUtils. 046 * 047 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 048 * 049 */ 050public class ReadWriteableMatrix extends Matrix implements ReadWriteable { 051 private static final long serialVersionUID = 1L; 052 053 /** 054 * Construct a new matrix of zero size. Only for IOUtils use. 055 */ 056 protected ReadWriteableMatrix() { 057 super(0, 0); 058 } 059 060 /** 061 * Construct a matrix using the provided 2-D double array. 062 * The array is assigned internally and is not copied. 063 * 064 * @param data the data 065 */ 066 public ReadWriteableMatrix(double[][] data) { 067 super(data); 068 } 069 070 /** 071 * Construct a new matrix of the given size 072 * @param rows Number of rows 073 * @param cols Number of columns 074 */ 075 public ReadWriteableMatrix(int rows, int cols) { 076 super(rows, cols); 077 } 078 079 /** 080 * Construct a matrix using the provided matrix. 081 * The matrix data is assigned internally and is not copied. 082 * 083 * @param data the data 084 */ 085 public ReadWriteableMatrix(Matrix data) { 086 this(data.getArray()); 087 } 088 089 @Override 090 public void readASCII(Scanner in) throws IOException { 091 final int rows = in.nextInt(); 092 final int cols = in.nextInt(); 093 094 double[][] data = new double[rows][cols]; 095 for (int r=0; r<rows; r++) 096 for (int c=0; c<cols; c++) 097 data[r][c] = in.nextDouble(); 098 099 setData(rows, cols, data); 100 } 101 102 @Override 103 public String asciiHeader() { 104 return this.getClass().getName() + " "; 105 } 106 107 @Override 108 public void readBinary(DataInput in) throws IOException { 109 final int rows = in.readInt(); 110 final int cols = in.readInt(); 111 112 double[][] data = new double[rows][cols]; 113 for (int r=0; r<rows; r++) 114 for (int c=0; c<cols; c++) 115 data[r][c] = in.readDouble(); 116 117 setData(rows, cols, data); 118 } 119 120 protected void setData(int m, int n, double[][] data) { 121 Class<Matrix> clz = Matrix.class; 122 try { 123 Field mField = clz.getDeclaredField("m"); 124 mField.setAccessible(true); 125 mField.setInt(this, m); 126 127 Field nField = clz.getDeclaredField("n"); 128 nField.setAccessible(true); 129 nField.setInt(this, n); 130 131 Field AField = clz.getDeclaredField("A"); 132 AField.setAccessible(true); 133 AField.set(this, data); 134 } catch (Exception e) { 135 throw new RuntimeException(e); 136 } 137 } 138 139 @Override 140 public byte[] binaryHeader() { 141 return "RWMAT".getBytes(); 142 } 143 144 @Override 145 public void writeASCII(PrintWriter out) throws IOException { 146 final int rows = this.getRowDimension(); 147 final int cols = this.getColumnDimension(); 148 final double[][] data = this.getArray(); 149 150 out.print(rows + " " + cols); 151 out.println(); 152 153 for (int r=0; r<rows; r++) { 154 for (int c=0; c<cols; c++) { 155 out.print(data[r][c] + " "); 156 } 157 out.println(); 158 } 159 } 160 161 @Override 162 public void writeBinary(DataOutput out) throws IOException { 163 final int rows = this.getRowDimension(); 164 final int cols = this.getColumnDimension(); 165 final double[][] data = this.getArray(); 166 167 out.writeInt(rows); 168 out.writeInt(cols); 169 170 for (int r=0; r<rows; r++) 171 for (int c=0; c<cols; c++) 172 out.writeDouble(data[r][c]); 173 } 174}