Coverage Report - eu.simuline.octave.io.impl.AbstractPrimitiveMatrixReader
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractPrimitiveMatrixReader
86%
40/46
72%
16/22
4.167
 
 1  
 /*
 2  
  * Copyright 2017 Ange Optimization ApS
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 
 17  
 
 18  
 package eu.simuline.octave.io.impl;
 19  
 
 20  
 import java.io.BufferedReader;
 21  
 
 22  
 import eu.simuline.octave.exception.OctaveParseException;
 23  
 import eu.simuline.octave.io.OctaveIO;
 24  
 import eu.simuline.octave.io.spi.OctaveDataReader;
 25  
 import eu.simuline.octave.type.matrix.AbstractGenericMatrix;
 26  
 
 27  
 /**
 28  
  * Common Reader class for matrices of primitive java types: 
 29  
  * Boolean, Double, Integer.... 
 30  
  *
 31  
  * @param <T>
 32  
  *    the type to be read in which has to extend {@link AbstractGenericMatrix}. 
 33  
  */
 34  562
 abstract class AbstractPrimitiveMatrixReader
 35  
     <T extends AbstractGenericMatrix<?,?>> 
 36  
     extends OctaveDataReader {
 37  
 
 38  
     // **** to be eliminated: is in according writer 
 39  
     protected static final String NDIMS    = "# ndims: ";
 40  
     protected static final String NROWS    = "# rows: ";
 41  
     protected static final String NCOLUMNS = "# columns: ";
 42  
 
 43  
 
 44  
     abstract T createOctaveValue(int[] size);
 45  
 
 46  
     /**
 47  
      * The matrix formats, e.g. <tt>matrix</tt> come in two variants: 
 48  
      * after line with "type" the next line either starts with 
 49  
      * <ul>
 50  
      * <li><tt># ndims: </tt> specifying the number of dimensions 
 51  
      * and in the next line the lengths in all these dimensions 
 52  
      * and all the following lines the vectorized data, 
 53  
      * each in a separate line. 
 54  
      * This is read by {@link #readVectorizedMatrix(BufferedReader, String)}. 
 55  
      * <li><tt># rows: </tt> specifying the number of rows 
 56  
      * and <tt># columns: </tt> specifying the number of columns 
 57  
      * in the next line (which works only for matrices, i.e. up to dimension 2) 
 58  
      * and then for each row a line follows 
 59  
      * each of which holds the entries separated by a blank. 
 60  
      * This is read by {@link #read2dmatrix(BufferedReader, String)}. 
 61  
      * </ul>
 62  
      */
 63  
     // **** caution: this distinction is valid only for floating point types. 
 64  
     // others use vectorized format only 
 65  
     // **** this may indicate inappropriate design. 
 66  
     @Override
 67  
     public T read(final BufferedReader reader) {
 68  554
         final String line = OctaveIO.readerReadLine(reader);
 69  
         // 2d or 2d+?
 70  554
         if (line.startsWith(NROWS)) {
 71  
             // this case does not occur for int types, 
 72  
             // just for float (including complex) and bool 
 73  
             // **** so this implementation may read things which do not occur 
 74  164
             return read2dmatrix(reader, line);
 75  390
         } else if (line.startsWith(NDIMS)) {
 76  390
             return readVectorizedMatrix(reader, line);
 77  
         } else {
 78  0
             throw new OctaveParseException
 79  
                 ("Expected <" + NROWS + "> or <" + NDIMS + 
 80  
                  ">, but got <" + line + ">. ");
 81  
         }
 82  
     }
 83  
 
 84  
     private T readVectorizedMatrix(BufferedReader reader, 
 85  
                                    String dimsLine) {
 86  390
         int[] size = readSizeVectorizedMatrix(reader, dimsLine);
 87  390
          T res = createOctaveValue(size);
 88  
           String line;
 89  
         // **** in the long run dataLength is not what we need 
 90  
         // active entries only 
 91  6362
         for (int idx = 0; idx < res.dataSize(); idx++) {
 92  5972
             line = OctaveIO.readerReadLine(reader);
 93  5972
              res.setPlain(line, idx);
 94  
         }
 95  390
         return res;
 96  
     }
 97  
 
 98  
     /**
 99  
      * Reads a line NDIMS &lt;num of dims> 
 100  
      * followed by a line of dimensions: integers separated by blank 
 101  
      * and returns an array with the according entries. 
 102  
      * In particluar the length is &lt;num of dims>. 
 103  
      */
 104  
     private int[] readSizeVectorizedMatrix(BufferedReader reader, 
 105  
                                            String ndimsLine) {
 106  390
         String line = ndimsLine;
 107  390
         if (!line.startsWith(NDIMS)) {
 108  0
             throw new OctaveParseException
 109  
                 ("Expected <" + NDIMS + ">, but got <" + line + ">. ");
 110  
         }
 111  390
         final int ndims = Integer.parseInt(line.substring(NDIMS.length()));
 112  
 
 113  390
         line = OctaveIO.readerReadLine(reader);
 114  390
         final String[] split = line.substring(1).split(" ");
 115  390
         if (split.length != ndims) {
 116  0
             throw new OctaveParseException
 117  
                 ("Expected <" + ndims + "> dimension, but got <" + 
 118  
                  split.length + "> (line was <" + line + ">). ");
 119  
         }
 120  390
         final int[] size = new int[split.length];
 121  1772
         for (int dim = 0; dim < split.length; dim++) {
 122  1382
             size[dim] = Integer.parseInt(split[dim]);
 123  
         }
 124  390
         return size;
 125  
     }
 126  
 
 127  
 
 128  
     // maybe this just throws an exception because this case does not occur. 
 129  
     private T read2dmatrix(BufferedReader reader, 
 130  
                            String rowsLine) {
 131  164
         int[] size = readSize2dmatrix(reader, rowsLine);
 132  164
         T res = createOctaveValue(size);
 133  
 
 134  164
         int rows    = size[0];
 135  164
         int columns = size[1];
 136  
         String line;
 137  
 
 138  674
         for (int r = 1; r <= rows; ++r) {
 139  510
             line = OctaveIO.readerReadLine(reader);
 140  510
             final String[] split = line.split(" ");
 141  510
             if (split.length != columns + 1) {
 142  0
                 throw new OctaveParseException
 143  
                     ("Error in matrix-format: '" + line + "'");
 144  
             }
 145  1406
             for (int c = 1; c < split.length; c++) {
 146  896
                 res.setPlain(split[c], (r - 1) + (c - 1) * rows);
 147  
             }
 148  
         }
 149  164
         return res;
 150  
     }
 151  
 
 152  
     /**
 153  
      * Reads lines NROWS &lt;num of rows> and NCOLUMNS &lt;num of cols>
 154  
      * and returns an array {nrows ncols}. 
 155  
      */
 156  
     protected int[] readSize2dmatrix(BufferedReader reader, 
 157  
                                      String rowsLine) {
 158  
         // # rows: 1
 159  164
         String line = rowsLine;
 160  164
         if (!line.startsWith(NROWS)) {
 161  0
             throw new OctaveParseException
 162  
                 ("Expected <" + NROWS + "> got <" + line + ">. ");
 163  
         }
 164  164
         final int rows = Integer.parseInt(line.substring(NROWS.length()));
 165  
         // # columns: 3
 166  164
         line = OctaveIO.readerReadLine(reader);
 167  164
         if (!line.startsWith(NCOLUMNS)) {
 168  0
             throw new OctaveParseException
 169  
                 ("Expected <" + NCOLUMNS + "> got <" + line + ">. ");
 170  
         }
 171  164
         final int columns = Integer.parseInt(line.substring(NCOLUMNS.length()));
 172  
         // 1 2 3
 173  
         // final int[] size = new int[2];
 174  
         // size[0] = rows;
 175  
         // size[1] = columns;
 176  164
         return new int[] {rows, columns};
 177  
     }
 178  
 }