--- /dev/null
+package org.simantics.modelica.reader;\r
+\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.simantics.modelica.data.DoubleMatrix;\r
+import org.simantics.modelica.data.IntMatrix;\r
+import org.simantics.modelica.data.Matrix;\r
+import org.simantics.modelica.data.StringMatrix;\r
+\r
+public class MatFileReader implements ResultFileReader {\r
+ private File file;\r
+ \r
+ private List<String> names = new ArrayList<String>();\r
+ private Map<String, Integer> indices = new HashMap<String, Integer>();\r
+ \r
+ \r
+ int readBytes = 0; // tracking read data\r
+ int dataMark = 0; // mark for actual data\r
+ \r
+ IntMatrix info;\r
+ int[] infoData;\r
+ \r
+ MatrixHeader dataHeader;\r
+ \r
+ public MatFileReader(File file) throws IOException {\r
+ this.file = file;\r
+ readVariables();\r
+ }\r
+ \r
+ public List<String> getNames() {\r
+ return names;\r
+ }\r
+ \r
+ public double[] readData(String item) throws IOException {\r
+ readBytes = 0;\r
+ Integer index = indices.get(item);\r
+ if (index == null)\r
+ throw new IOException("Unknown item: " + item);\r
+ InputStream in = new FileInputStream(file);\r
+ skip(dataMark, in);\r
+ \r
+ Object data = readColumn(dataHeader, index, in);\r
+ \r
+ in.close();\r
+ \r
+ return (double[])data;\r
+\r
+ }\r
+ \r
+ \r
+ private void readVariables() throws IOException {\r
+ InputStream in = new FileInputStream(file);\r
+ readMatrix(in); // Header\r
+ StringMatrix names = (StringMatrix)readMatrix(in); // Variable names\r
+ readMatrix(in); // Variable descriptions\r
+ \r
+ for (int i = 0; i < names.data.length; i++) {\r
+ String s = names.data[i];\r
+ this.names.add(s);\r
+ indices.put(s, i);\r
+ }\r
+ \r
+ \r
+ \r
+ info = (IntMatrix)readMatrix(in); // Data info\r
+ \r
+ if(info.rows != 4 || info.columns != names.rows )\r
+ throw new IOException("Invalid result data.");\r
+ \r
+ infoData = info.data;\r
+ \r
+ readMatrix(in); // Some result data matrix?\r
+ \r
+ dataHeader = new MatrixHeader(in);\r
+ \r
+ dataMark = readBytes;\r
+ \r
+ in.close();\r
+ \r
+ // filter incompatible? data.\r
+ for (int i = this.names.size() -1; i >= 0; i--) {\r
+ if (infoData[i * 4] != 2) {\r
+ String name = this.names.remove(i);\r
+ this.indices.remove(name);\r
+ }\r
+ \r
+ }\r
+ \r
+ Collections.sort(this.names);\r
+ \r
+ }\r
+\r
+ private final int getInt(InputStream in) throws IOException {\r
+ int ch1 = in.read();\r
+ int ch2 = in.read();\r
+ int ch3 = in.read();\r
+ int ch4 = in.read();\r
+ readBytes += 4;\r
+ return ((ch1 << 0) + (ch2 << 8) + (ch3 << 16) + (ch4 << 24));\r
+ }\r
+\r
+ private final long getLong(InputStream in) throws IOException {\r
+ int ch1 = in.read();\r
+ int ch2 = in.read();\r
+ int ch3 = in.read();\r
+ int ch4 = in.read();\r
+ int ch5 = in.read();\r
+ int ch6 = in.read();\r
+ int ch7 = in.read();\r
+ int ch8 = in.read();\r
+ readBytes += 8;\r
+ return ((((long)ch1) << 0) + (((long)ch2) << 8) + (((long)ch3) << 16) + (((long)ch4) << 24) +\r
+ (((long)ch5) << 32) + (((long)ch6) << 40) + (((long)ch7) << 48) + (((long)ch8) << 56));\r
+ }\r
+\r
+ private final double getDouble(InputStream in) throws IOException {\r
+ return Double.longBitsToDouble(getLong(in));\r
+ }\r
+\r
+ private String getString(InputStream in,int length) throws IOException {\r
+ byte[] buffer = new byte[length];\r
+ int pos = 0;\r
+ while(pos < length)\r
+ pos += in.read(buffer, pos, length-pos);\r
+ readBytes += length;\r
+ return new String(buffer, "UTF-8");\r
+ }\r
+\r
+ private Matrix readMatrix(InputStream in) throws IOException {\r
+ \r
+ \r
+ int type = getInt(in);\r
+ int rows = getInt(in);\r
+ int columns = getInt(in);\r
+ int imagf = getInt(in);\r
+ int namlen = getInt(in);\r
+\r
+ String name = getString(in,namlen-1);\r
+ in.read();\r
+ readBytes++;\r
+ \r
+ \r
+\r
+ if(imagf > 0)\r
+ throw new IOException("Imaginary part of the matrix is not supported (matrix " + name + ").");\r
+\r
+ switch(type) {\r
+ case 0: {\r
+ DoubleMatrix matrix = new DoubleMatrix(name, rows, columns);\r
+ int size = rows*columns;\r
+ double[] data = matrix.data;\r
+ for(int i=0;i<size;++i)\r
+ data[i] = getDouble(in);\r
+ return matrix;\r
+ } \r
+ case 20: {\r
+ IntMatrix matrix = new IntMatrix(name, rows, columns);\r
+ int size = rows*columns;\r
+ int[] data = matrix.data;\r
+ for(int i=0;i<size;++i)\r
+ data[i] = getInt(in);\r
+ return matrix;\r
+ }\r
+ case 51: {\r
+ StringMatrix matrix = new StringMatrix(name, columns);\r
+ String[] data = matrix.data;\r
+ for(int i=0;i<columns;++i)\r
+ data[i] = getString(in,rows).trim();\r
+ return matrix;\r
+ }\r
+ default:\r
+ throw new IOException("Matrix " + name + " has unsupported data type " + type + ".");\r
+ }\r
+ }\r
+ \r
+ private Matrix readMatrix(MatrixHeader header, InputStream in) throws IOException {\r
+ \r
+ \r
+\r
+\r
+ switch(header.type) {\r
+ case 0: {\r
+ DoubleMatrix matrix = new DoubleMatrix(header.name, header.rows,header.columns);\r
+ int size = header.rows*header.columns;\r
+ double[] data = matrix.data;\r
+ for(int i=0;i<size;++i)\r
+ data[i] = getDouble(in);\r
+ return matrix;\r
+ } \r
+ case 20: {\r
+ IntMatrix matrix = new IntMatrix(header.name, header.rows, header.columns);\r
+ int size = header.rows*header.columns;\r
+ int[] data = matrix.data;\r
+ for(int i=0;i<size;++i)\r
+ data[i] = getInt(in);\r
+ return matrix;\r
+ }\r
+ case 51: {\r
+ StringMatrix matrix = new StringMatrix(header.name, header.columns);\r
+ String[] data = matrix.data;\r
+ for(int i=0;i<header.columns;++i)\r
+ data[i] = getString(in,header.rows).trim();\r
+ return matrix;\r
+ }\r
+ default:\r
+ throw new IOException("Matrix " + header.name + " has unsupported data type " + header.type + ".");\r
+ }\r
+ }\r
+ \r
+ private double[] readColumn(MatrixHeader header, int column, InputStream in)throws IOException {\r
+ boolean fast = true;\r
+\r
+ if (header.type != 0)\r
+ throw new IOException("Only double type supported");\r
+ \r
+ if (infoData[column * 4] != 2)\r
+ throw new IOException(); // this is checked in initialization phase.\r
+ int size = header.columns;\r
+ int rows = header.rows;\r
+ double[] v = new double[size];\r
+ int sc = infoData[column * 4 + 1];\r
+ int c = sc > 0 ? sc-1 : 1-sc;\r
+ \r
+ if (fast) {\r
+\r
+ skip(c * 8, in);\r
+ for (int j = 0; j < v.length; ++j) {\r
+ \r
+ double d = getDouble(in);\r
+ v[j] = d;\r
+ skip((rows-1)*8,in);\r
+ }\r
+\r
+ } else {\r
+ DoubleMatrix values = (DoubleMatrix)readMatrix(header, in);\r
+ \r
+ double[] valueData = values.data;\r
+\r
+\r
+ for(int j=0;j<v.length;++j) {\r
+ v[j] = valueData[rows * j + c];\r
+ }\r
+\r
+ }\r
+ if(sc < 0)\r
+ for(int j=0;j<v.length;++j)\r
+ v[j] = -v[j];\r
+ return v;\r
+ }\r
+ \r
+ private void skip(int skipBytes, InputStream in) throws IOException {\r
+ int skip = 0; \r
+ while (skip < skipBytes) {\r
+ skip += in.skip(skipBytes-skip);\r
+ }\r
+ }\r
+ \r
+ \r
+ private class MatrixHeader {\r
+ \r
+ int type;\r
+ int rows;\r
+ int columns;\r
+ int imagf;\r
+ int namlen;\r
+ \r
+ String name;\r
+ \r
+ public MatrixHeader(InputStream in) throws IOException{\r
+ int s = readBytes;\r
+ type = getInt(in);\r
+ rows = getInt(in);\r
+ columns = getInt(in);\r
+ imagf = getInt(in);\r
+ namlen = getInt(in);\r
+\r
+ name = getString(in,namlen-1);\r
+ in.read();\r
+ readBytes++;\r
+ if(imagf > 0)\r
+ throw new IOException("Imaginary part of the matrix is not supported (matrix " + name + ").");\r
+ \r
+ }\r
+ }\r
+}\r