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 @Override
72 public final int cardinality()
73 {
74 return (int) Arrays.stream(this.matrixSI).parallel().filter(d -> d != 0.0).count();
75 }
76
77 @Override
78 public final DoubleMatrixDataDense assign(final DoubleFunction doubleFunction)
79 {
80 IntStream.range(0, this.rows() * this.cols()).parallel()
81 .forEach(i -> this.matrixSI[i] = doubleFunction.apply(this.matrixSI[i]));
82 return this;
83 }
84
85 @Override
86 public final DoubleMatrixDataDense assign(final DoubleFunction2 doubleFunction, final DoubleMatrixData right)
87 {
88 if (right.isDense())
89 {
90 DoubleMatrixDataDense rightDense = (DoubleMatrixDataDense) right;
91 IntStream.range(0, this.rows() * this.cols()).parallel()
92 .forEach(i -> this.matrixSI[i] = doubleFunction.apply(this.matrixSI[i], rightDense.matrixSI[i]));
93 }
94 else
95 {
96 IntStream.range(0, this.rows() * this.cols()).parallel().forEach(
97 i -> this.matrixSI[i] = doubleFunction.apply(this.matrixSI[i], right.getSI(i / this.cols, i % this.cols)));
98 }
99 return this;
100 }
101
102 @Override
103 public final DoubleMatrixDataDense toDense()
104 {
105 return this;
106 }
107
108 @Override
109 public final DoubleMatrixDataSparse toSparse()
110 {
111 int length = cardinality();
112 double[] sparseSI = new double[length];
113 long[] indices = new long[length];
114 int count = 0;
115 for (int r = 0; r < this.rows; r++)
116 {
117 for (int c = 0; c < this.cols; c++)
118 {
119 int index = r * this.cols + c;
120 if (this.matrixSI[index] != 0.0)
121 {
122 sparseSI[count] = this.matrixSI[index];
123 indices[count] = index;
124 count++;
125 }
126 }
127 }
128 return new DoubleMatrixDataSparse(sparseSI, indices, this.rows, this.cols);
129 }
130
131 @Override
132 public final double getSI(final int row, final int col)
133 {
134 return this.matrixSI[row * this.cols + col];
135 }
136
137 @Override
138 public final void setSI(final int row, final int col, final double valueSI)
139 {
140 this.matrixSI[row * this.cols + col] = valueSI;
141 }
142
143 @Override
144 public final double[][] getDenseMatrixSI()
145 {
146 double[][] matrix = new double[this.rows][];
147 for (int r = 0; r < this.rows; r++)
148 {
149 double[] row = new double[this.cols];
150 System.arraycopy(this.matrixSI, r * this.cols, row, 0, row.length);
151 matrix[r] = row;
152 }
153 return matrix;
154 }
155
156 @Override
157 public final DoubleMatrixDataDense copy()
158 {
159 try
160 {
161 return new DoubleMatrixDataDense(getDenseMatrixSI());
162 }
163 catch (ValueRuntimeException exception)
164 {
165 throw new RuntimeException(exception);
166 }
167 }
168
169 @Override
170 public DoubleMatrixData plus(final DoubleMatrixData right) throws ValueRuntimeException
171 {
172 checkSizes(right);
173 double[] dm = new double[this.rows * this.cols];
174 if (right.isDense())
175 {
176 IntStream.range(0, this.rows).parallel().forEach(r -> IntStream.range(0, this.cols).forEach(
177 c -> dm[r * this.cols + c] = this.matrixSI[r * this.cols + c] + right.matrixSI[r * this.cols + c]));
178 }
179 else
180 {
181 IntStream.range(0, this.rows).parallel().forEach(r -> IntStream.range(0, this.cols)
182 .forEach(c -> dm[r * this.cols + c] = this.matrixSI[r * this.cols + c] + right.getSI(r, c)));
183 }
184 return new DoubleMatrixDataDense(dm, this.rows, this.cols);
185 }
186
187 @Override
188 public final DoubleMatrixDataDense minus(final DoubleMatrixData right)
189 {
190 checkSizes(right);
191 double[] dm = new double[this.rows * this.cols];
192 if (right.isDense())
193 {
194 IntStream.range(0, this.rows).parallel().forEach(r -> IntStream.range(0, this.cols).forEach(
195 c -> dm[r * this.cols + c] = this.matrixSI[r * this.cols + c] - right.matrixSI[r * this.cols + c]));
196 }
197 else
198 {
199 IntStream.range(0, this.rows).parallel().forEach(r -> IntStream.range(0, this.cols)
200 .forEach(c -> dm[r * this.cols + c] = this.matrixSI[r * this.cols + c] - right.getSI(r, c)));
201 }
202 return new DoubleMatrixDataDense(dm, this.rows, this.cols);
203 }
204
205 @Override
206 public DoubleMatrixData times(final DoubleMatrixData right) throws ValueRuntimeException
207 {
208 if (right.isSparse())
209 {
210
211 return right.times(this);
212 }
213
214 checkSizes(right);
215 return this.copy().multiplyBy(right);
216 }
217
218 @Override
219 public DoubleMatrixData divide(final DoubleMatrixData right) throws ValueRuntimeException
220 {
221 checkSizes(right);
222 double[] dm = new double[this.rows * this.cols];
223 if (right.isDense())
224 {
225 IntStream.range(0, this.rows * this.cols).parallel().forEach(i -> dm[i] = this.matrixSI[i] / right.matrixSI[i]);
226 }
227 else
228 {
229 IntStream.range(0, this.rows).parallel().forEach(r -> IntStream.range(0, this.cols)
230 .forEach(c -> dm[r * this.cols + c] = this.matrixSI[r * this.cols + c] / right.getSI(r, c)));
231 }
232 return new DoubleMatrixDataDense(dm, this.rows, this.cols);
233 }
234
235 @Override
236 public String toString()
237 {
238 return "DoubleMatrixDataDense [storageType=" + getStorageType() + ", matrixSI=" + Arrays.toString(this.matrixSI) + "]";
239 }
240
241 }