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