View Javadoc
1   package org.djunits.value.vfloat.matrix.data;
2   
3   import java.util.stream.IntStream;
4   
5   import org.djunits.value.ValueRuntimeException;
6   import org.djunits.value.storage.StorageType;
7   import org.djunits.value.vfloat.function.FloatFunction;
8   import org.djunits.value.vfloat.function.FloatFunction2;
9   
10  /**
11   * Stores dense data for a FloatMatrix and carries out basic operations.
12   * <p>
13   * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
14   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
15   * </p>
16   * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
17   * @author <a href="https://www.tudelft.nl/staff/p.knoppers/">Peter Knoppers</a>
18   */
19  public class FloatMatrixDataDense extends FloatMatrixData
20  {
21      /** */
22      private static final long serialVersionUID = 1L;
23  
24      /**
25       * Create a matrix with dense data.
26       * @param matrixSI float[]; the data to store
27       * @param rows int; the number of rows
28       * @param cols int; the number of columns
29       * @throws ValueRuntimeException in case <code>rows * cols != matrixSI.length</code>
30       */
31      public FloatMatrixDataDense(final float[] matrixSI, final int rows, final int cols) throws ValueRuntimeException
32      {
33          super(StorageType.DENSE);
34          if (rows * cols != matrixSI.length)
35          {
36              throw new ValueRuntimeException("FloatMatrixDataDense constructor, rows * cols != matrixSI.length");
37          }
38          this.matrixSI = new float[matrixSI.length];
39          System.arraycopy(matrixSI, 0, this.matrixSI, 0, matrixSI.length);
40          this.rows = rows;
41          this.cols = cols;
42      }
43  
44      /**
45       * Create a matrix with dense data. The float array is of the form d[rows][columns] so each value can be found with
46       * f[row][column].
47       * @param matrixSI float[][]; the data to store
48       * @throws ValueRuntimeException in case matrix is ragged
49       */
50      public FloatMatrixDataDense(final float[][] matrixSI) throws ValueRuntimeException
51      {
52          super(StorageType.DENSE);
53          if (matrixSI == null || matrixSI.length == 0)
54          {
55              throw new ValueRuntimeException("FloatMatrixDataDense constructor, matrixSI == null || matrixSI.length == 0");
56          }
57          this.rows = matrixSI.length;
58          this.cols = matrixSI[0].length;
59          this.matrixSI = new float[this.rows * this.cols];
60          for (int r = 0; r < this.rows; r++)
61          {
62              float[] row = matrixSI[r];
63              if (row.length != this.cols)
64              {
65                  throw new ValueRuntimeException("FloatMatrixDataDense constructor, ragged matrix");
66              }
67              System.arraycopy(row, 0, this.matrixSI, r * this.cols, row.length);
68          }
69      }
70  
71      /** {@inheritDoc} */
72      @Override
73      public final int cardinality()
74      {
75          // this does not copy the data. See http://stackoverflow.com/questions/23106093/how-to-get-a-stream-from-a-float
76          return (int) IntStream.range(0, this.matrixSI.length).parallel().mapToDouble(i -> this.matrixSI[i])
77                  .filter(d -> d != 0.0).count();
78      }
79  
80      /** {@inheritDoc} */
81      @Override
82      public final FloatMatrixDataDense assign(final FloatFunction floatFunction)
83      {
84          IntStream.range(0, this.rows() * this.cols()).parallel()
85                  .forEach(i -> this.matrixSI[i] = floatFunction.apply(this.matrixSI[i]));
86          return this;
87      }
88  
89      /** {@inheritDoc} */
90      @Override
91      public final FloatMatrixDataDense assign(final FloatFunction2 floatFunction, final FloatMatrixData right)
92      {
93          if (right.isDense())
94          {
95              FloatMatrixDataDenseorg/djunits/value/vfloat/matrix/data/FloatMatrixDataDense.html#FloatMatrixDataDense">FloatMatrixDataDense rightDense = (FloatMatrixDataDense) right;
96              IntStream.range(0, this.rows() * this.cols()).parallel()
97                      .forEach(i -> this.matrixSI[i] = floatFunction.apply(this.matrixSI[i], rightDense.matrixSI[i]));
98          }
99          else
100         {
101             IntStream.range(0, this.rows() * this.cols()).parallel().forEach(
102                     i -> this.matrixSI[i] = floatFunction.apply(this.matrixSI[i], right.getSI(i / this.cols, i % this.cols)));
103         }
104         return this;
105     }
106 
107     /** {@inheritDoc} */
108     @Override
109     public final FloatMatrixDataDense toDense()
110     {
111         return this;
112     }
113 
114     /** {@inheritDoc} */
115     @Override
116     public final FloatMatrixDataSparse toSparse()
117     {
118         int length = cardinality();
119         float[] sparseSI = new float[length];
120         long[] indices = new long[length];
121         int count = 0;
122         for (int r = 0; r < this.rows; r++)
123         {
124             for (int c = 0; c < this.cols; c++)
125             {
126                 int index = r * this.cols + c;
127                 if (this.matrixSI[index] != 0.0)
128                 {
129                     sparseSI[count] = this.matrixSI[index];
130                     indices[count] = index;
131                     count++;
132                 }
133             }
134         }
135         return new FloatMatrixDataSparse(sparseSI, indices, this.rows, this.cols);
136     }
137 
138     /** {@inheritDoc} */
139     @Override
140     public final float getSI(final int row, final int col)
141     {
142         return this.matrixSI[row * this.cols + col];
143     }
144 
145     /** {@inheritDoc} */
146     @Override
147     public final void setSI(final int row, final int col, final float valueSI)
148     {
149         this.matrixSI[row * this.cols + col] = valueSI;
150     }
151 
152     /** {@inheritDoc} */
153     @Override
154     public final float[][] getDenseMatrixSI()
155     {
156         float[][] matrix = new float[this.rows][];
157         for (int r = 0; r < this.rows; r++)
158         {
159             float[] row = new float[this.cols];
160             System.arraycopy(this.matrixSI, r * this.cols, row, 0, row.length);
161             matrix[r] = row;
162         }
163         return matrix;
164     }
165 
166     /** {@inheritDoc} */
167     @Override
168     public final double[][] getDoubleDenseMatrixSI()
169     {
170         double[][] matrix = new double[this.rows][];
171         for (int r = 0; r < this.rows; r++)
172         {
173             double[] row = new double[this.cols];
174             int offset = r * this.cols;
175             for (int c = 0; c < this.cols; c++)
176             {
177                 row[c] = this.matrixSI[offset++];
178             }
179             matrix[r] = row;
180         }
181         return matrix;
182     }
183 
184     /** {@inheritDoc} */
185     @Override
186     public final FloatMatrixDataDense copy()
187     {
188         try
189         {
190             return new FloatMatrixDataDense(getDenseMatrixSI());
191         }
192         catch (ValueRuntimeException exception)
193         {
194             throw new RuntimeException(exception); // should not happen -- original is not ragged...
195         }
196     }
197 
198     /** {@inheritDoc} */
199     @Override
200     public FloatMatrixDataix/data/FloatMatrixData.html#FloatMatrixData">FloatMatrixData plus(final FloatMatrixData right) throws ValueRuntimeException
201     {
202         checkSizes(right);
203         float[] fm = new float[this.rows * this.cols];
204         if (right.isDense())
205         {
206             IntStream.range(0, this.rows).parallel().forEach(r -> IntStream.range(0, this.cols).forEach(
207                     c -> fm[r * this.cols + c] = this.matrixSI[r * this.cols + c] + right.matrixSI[r * this.cols + c]));
208         }
209         else
210         { // right is sparse
211             IntStream.range(0, this.rows).parallel().forEach(r -> IntStream.range(0, this.cols)
212                     .forEach(c -> fm[r * this.cols + c] = this.matrixSI[r * this.cols + c] + right.getSI(r, c)));
213         }
214         return new FloatMatrixDataDense(fm, this.rows, this.cols);
215     }
216 
217     /** {@inheritDoc} */
218     @Override
219     public final FloatMatrixDataDense minus(final FloatMatrixData right)
220     {
221         checkSizes(right);
222         float[] fm = new float[this.rows * this.cols];
223         if (right.isDense())
224         {
225             IntStream.range(0, this.rows).parallel().forEach(r -> IntStream.range(0, this.cols).forEach(
226                     c -> fm[r * this.cols + c] = this.matrixSI[r * this.cols + c] - right.matrixSI[r * this.cols + c]));
227         }
228         else
229         { // right is sparse
230             IntStream.range(0, this.rows).parallel().forEach(r -> IntStream.range(0, this.cols)
231                     .forEach(c -> fm[r * this.cols + c] = this.matrixSI[r * this.cols + c] - right.getSI(r, c)));
232         }
233         return new FloatMatrixDataDense(fm, this.rows, this.cols);
234     }
235 
236     /** {@inheritDoc} */
237     @Override
238     public FloatMatrixDatax/data/FloatMatrixData.html#FloatMatrixData">FloatMatrixData times(final FloatMatrixData right) throws ValueRuntimeException
239     {
240         if (right.isSparse())
241         {
242             // result shall be sparse
243             return right.times(this);
244         }
245         // Both are dense
246         checkSizes(right);
247         return this.copy().multiplyBy(right);
248     }
249 
250     /** {@inheritDoc} */
251     @Override
252     public FloatMatrixData/data/FloatMatrixData.html#FloatMatrixData">FloatMatrixData divide(final FloatMatrixData right) throws ValueRuntimeException
253     {
254         checkSizes(right);
255         return this.copy().divideBy(right);
256     }
257 
258 }