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 import org.djutils.exceptions.Throw;
11
12
13
14
15
16
17
18
19
20
21 public class DoubleMatrixDataDense extends DoubleMatrixData
22 {
23
24 private static final long serialVersionUID = 1L;
25
26
27
28
29
30
31
32
33 public DoubleMatrixDataDense(final double[] matrixSI, final int rows, final int cols) throws ValueRuntimeException
34 {
35 super(StorageType.DENSE);
36 if (rows * cols != matrixSI.length)
37 {
38 throw new ValueRuntimeException("DoubleMatrixDataDense constructor, rows * cols != matrixSI.length");
39 }
40 this.matrixSI = new double[matrixSI.length];
41 System.arraycopy(matrixSI, 0, this.matrixSI, 0, matrixSI.length);
42 this.rows = rows;
43 this.cols = cols;
44 }
45
46
47
48
49
50
51
52
53 public DoubleMatrixDataDense(final double[][] matrixSI) throws ValueRuntimeException
54 {
55 super(StorageType.DENSE);
56 Throw.whenNull(matrixSI, "DoubleMatrixDataDense constructor, matrixSI == null");
57 this.rows = matrixSI.length;
58 this.cols = this.rows == 0 ? 0 : matrixSI[0].length;
59 this.matrixSI = new double[this.rows * this.cols];
60 for (int r = 0; r < this.rows; r++)
61 {
62 double[] row = matrixSI[r];
63 if (row.length != this.cols)
64 {
65 throw new ValueRuntimeException("DoubleMatrixDataDense constructor, ragged matrix");
66 }
67 System.arraycopy(row, 0, this.matrixSI, r * this.cols, row.length);
68 }
69 }
70
71
72 @Override
73 public final int cardinality()
74 {
75 return (int) Arrays.stream(this.matrixSI).parallel().filter(d -> d != 0.0).count();
76 }
77
78
79 @Override
80 public final DoubleMatrixDataDense assign(final DoubleFunction doubleFunction)
81 {
82 IntStream.range(0, this.rows() * this.cols()).parallel()
83 .forEach(i -> this.matrixSI[i] = doubleFunction.apply(this.matrixSI[i]));
84 return this;
85 }
86
87
88 @Override
89 public final DoubleMatrixDataDense assign(final DoubleFunction2 doubleFunction, final DoubleMatrixData right)
90 {
91 if (right.isDense())
92 {
93 DoubleMatrixDataDense rightDense = (DoubleMatrixDataDense) right;
94 IntStream.range(0, this.rows() * this.cols()).parallel()
95 .forEach(i -> this.matrixSI[i] = doubleFunction.apply(this.matrixSI[i], rightDense.matrixSI[i]));
96 }
97 else
98 {
99 IntStream.range(0, this.rows() * this.cols()).parallel().forEach(
100 i -> this.matrixSI[i] = doubleFunction.apply(this.matrixSI[i], right.getSI(i / this.cols, i % this.cols)));
101 }
102 return this;
103 }
104
105
106 @Override
107 public final DoubleMatrixDataDense toDense()
108 {
109 return this;
110 }
111
112
113 @Override
114 public final DoubleMatrixDataSparse toSparse()
115 {
116 int length = cardinality();
117 double[] sparseSI = new double[length];
118 long[] indices = new long[length];
119 int count = 0;
120 for (int r = 0; r < this.rows; r++)
121 {
122 for (int c = 0; c < this.cols; c++)
123 {
124 int index = r * this.cols + c;
125 if (this.matrixSI[index] != 0.0)
126 {
127 sparseSI[count] = this.matrixSI[index];
128 indices[count] = index;
129 count++;
130 }
131 }
132 }
133 return new DoubleMatrixDataSparse(sparseSI, indices, this.rows, this.cols);
134 }
135
136
137 @Override
138 public final double getSI(final int row, final int col)
139 {
140 return this.matrixSI[row * this.cols + col];
141 }
142
143
144 @Override
145 public final void setSI(final int row, final int col, final double valueSI)
146 {
147 this.matrixSI[row * this.cols + col] = valueSI;
148 }
149
150
151 @Override
152 public final double[][] getDenseMatrixSI()
153 {
154 double[][] matrix = new double[this.rows][];
155 for (int r = 0; r < this.rows; r++)
156 {
157 double[] row = new double[this.cols];
158 System.arraycopy(this.matrixSI, r * this.cols, row, 0, row.length);
159 matrix[r] = row;
160 }
161 return matrix;
162 }
163
164
165 @Override
166 public final DoubleMatrixDataDense copy()
167 {
168 try
169 {
170 return new DoubleMatrixDataDense(getDenseMatrixSI());
171 }
172 catch (ValueRuntimeException exception)
173 {
174 throw new RuntimeException(exception);
175 }
176 }
177
178
179 @Override
180 public DoubleMatrixData plus(final DoubleMatrixData right) throws ValueRuntimeException
181 {
182 checkSizes(right);
183 double[] dm = new double[this.rows * this.cols];
184 if (right.isDense())
185 {
186 IntStream.range(0, this.rows).parallel().forEach(r -> IntStream.range(0, this.cols).forEach(
187 c -> dm[r * this.cols + c] = this.matrixSI[r * this.cols + c] + right.matrixSI[r * this.cols + c]));
188 }
189 else
190 {
191 IntStream.range(0, this.rows).parallel().forEach(r -> IntStream.range(0, this.cols)
192 .forEach(c -> dm[r * this.cols + c] = this.matrixSI[r * this.cols + c] + right.getSI(r, c)));
193 }
194 return new DoubleMatrixDataDense(dm, this.rows, this.cols);
195 }
196
197
198 @Override
199 public final DoubleMatrixDataDense minus(final DoubleMatrixData right)
200 {
201 checkSizes(right);
202 double[] dm = new double[this.rows * this.cols];
203 if (right.isDense())
204 {
205 IntStream.range(0, this.rows).parallel().forEach(r -> IntStream.range(0, this.cols).forEach(
206 c -> dm[r * this.cols + c] = this.matrixSI[r * this.cols + c] - right.matrixSI[r * this.cols + c]));
207 }
208 else
209 {
210 IntStream.range(0, this.rows).parallel().forEach(r -> IntStream.range(0, this.cols)
211 .forEach(c -> dm[r * this.cols + c] = this.matrixSI[r * this.cols + c] - right.getSI(r, c)));
212 }
213 return new DoubleMatrixDataDense(dm, this.rows, this.cols);
214 }
215
216
217 @Override
218 public DoubleMatrixData times(final DoubleMatrixData right) throws ValueRuntimeException
219 {
220 if (right.isSparse())
221 {
222
223 return right.times(this);
224 }
225
226 checkSizes(right);
227 return this.copy().multiplyBy(right);
228 }
229
230
231 @Override
232 public DoubleMatrixData divide(final DoubleMatrixData right) throws ValueRuntimeException
233 {
234 checkSizes(right);
235 double[] dm = new double[this.rows * this.cols];
236 if (right.isDense())
237 {
238 IntStream.range(0, this.rows * this.cols).parallel().forEach(i -> dm[i] = this.matrixSI[i] / right.matrixSI[i]);
239 }
240 else
241 {
242 IntStream.range(0, this.rows).parallel().forEach(r -> IntStream.range(0, this.cols)
243 .forEach(c -> dm[r * this.cols + c] = this.matrixSI[r * this.cols + c] / right.getSI(r, c)));
244 }
245 return new DoubleMatrixDataDense(dm, this.rows, this.cols);
246 }
247
248
249 @Override
250 public String toString()
251 {
252 return "DoubleMatrixDataDense [storageType=" + getStorageType() + ", matrixSI=" + Arrays.toString(this.matrixSI) + "]";
253 }
254
255 }