1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.math4.legacy.linear;
19
20 import java.io.Serializable;
21
22 import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
23 import org.apache.commons.math4.legacy.exception.NotStrictlyPositiveException;
24 import org.apache.commons.math4.legacy.exception.NumberIsTooLargeException;
25 import org.apache.commons.math4.legacy.exception.OutOfRangeException;
26
27
28
29
30
31
32
33
34
35
36
37
38
39 public class OpenMapRealMatrix extends AbstractRealMatrix
40 implements SparseRealMatrix, Serializable {
41
42 private static final long serialVersionUID = -5962461716457143437L;
43
44 private final int rows;
45
46 private final int columns;
47
48 private final OpenIntToDoubleHashMap entries;
49
50
51
52
53
54
55
56
57
58
59
60 public OpenMapRealMatrix(int rowDimension, int columnDimension)
61 throws NotStrictlyPositiveException, NumberIsTooLargeException {
62 super(rowDimension, columnDimension);
63 long lRow = rowDimension;
64 long lCol = columnDimension;
65 if (lRow * lCol >= Integer.MAX_VALUE) {
66 throw new NumberIsTooLargeException(lRow * lCol, Integer.MAX_VALUE, false);
67 }
68 this.rows = rowDimension;
69 this.columns = columnDimension;
70 this.entries = new OpenIntToDoubleHashMap(0.0);
71 }
72
73
74
75
76
77
78 public OpenMapRealMatrix(OpenMapRealMatrix matrix) {
79 this.rows = matrix.rows;
80 this.columns = matrix.columns;
81 this.entries = new OpenIntToDoubleHashMap(matrix.entries);
82 }
83
84
85 @Override
86 public OpenMapRealMatrix copy() {
87 return new OpenMapRealMatrix(this);
88 }
89
90
91
92
93
94
95
96 @Override
97 public OpenMapRealMatrix createMatrix(int rowDimension, int columnDimension)
98 throws NotStrictlyPositiveException, NumberIsTooLargeException {
99 return new OpenMapRealMatrix(rowDimension, columnDimension);
100 }
101
102
103 @Override
104 public int getColumnDimension() {
105 return columns;
106 }
107
108
109
110
111
112
113
114
115
116 public OpenMapRealMatrix add(OpenMapRealMatrix m)
117 throws MatrixDimensionMismatchException {
118
119 MatrixUtils.checkAdditionCompatible(this, m);
120
121 final OpenMapRealMatrix out = new OpenMapRealMatrix(this);
122 for (OpenIntToDoubleHashMap.Iterator iterator = m.entries.iterator(); iterator.hasNext();) {
123 iterator.advance();
124 final int row = iterator.key() / columns;
125 final int col = iterator.key() - row * columns;
126 out.setEntry(row, col, getEntry(row, col) + iterator.value());
127 }
128
129 return out;
130 }
131
132
133 @Override
134 public OpenMapRealMatrix subtract(final RealMatrix m)
135 throws MatrixDimensionMismatchException {
136 if (m instanceof OpenMapRealMatrix) {
137 return subtract((OpenMapRealMatrix) m);
138 }
139 return (OpenMapRealMatrix) super.subtract(m);
140 }
141
142
143
144
145
146
147
148
149
150 public OpenMapRealMatrix subtract(OpenMapRealMatrix m)
151 throws MatrixDimensionMismatchException {
152 MatrixUtils.checkAdditionCompatible(this, m);
153
154 final OpenMapRealMatrix out = new OpenMapRealMatrix(this);
155 for (OpenIntToDoubleHashMap.Iterator iterator = m.entries.iterator(); iterator.hasNext();) {
156 iterator.advance();
157 final int row = iterator.key() / columns;
158 final int col = iterator.key() - row * columns;
159 out.setEntry(row, col, getEntry(row, col) - iterator.value());
160 }
161
162 return out;
163 }
164
165
166
167
168
169
170
171
172 @Override
173 public RealMatrix multiply(final RealMatrix m)
174 throws DimensionMismatchException, NumberIsTooLargeException {
175 if (m instanceof OpenMapRealMatrix) {
176 return multiply((OpenMapRealMatrix) m);
177 }
178
179 MatrixUtils.checkMultiplicationCompatible(this, m);
180
181 final int outCols = m.getColumnDimension();
182 final BlockRealMatrix out = new BlockRealMatrix(rows, outCols);
183 for (OpenIntToDoubleHashMap.Iterator iterator = entries.iterator(); iterator.hasNext();) {
184 iterator.advance();
185 final double value = iterator.value();
186 final int key = iterator.key();
187 final int i = key / columns;
188 final int k = key % columns;
189 for (int j = 0; j < outCols; ++j) {
190 out.addToEntry(i, j, value * m.getEntry(k, j));
191 }
192 }
193
194 return out;
195 }
196
197
198
199
200
201
202
203
204
205
206
207 public OpenMapRealMatrix multiply(OpenMapRealMatrix m)
208 throws DimensionMismatchException, NumberIsTooLargeException {
209
210 MatrixUtils.checkMultiplicationCompatible(this, m);
211
212 final int outCols = m.getColumnDimension();
213 OpenMapRealMatrix out = new OpenMapRealMatrix(rows, outCols);
214 for (OpenIntToDoubleHashMap.Iterator iterator = entries.iterator(); iterator.hasNext();) {
215 iterator.advance();
216 final double value = iterator.value();
217 final int key = iterator.key();
218 final int i = key / columns;
219 final int k = key % columns;
220 for (int j = 0; j < outCols; ++j) {
221 final int rightKey = m.computeKey(k, j);
222 if (m.entries.containsKey(rightKey)) {
223 final int outKey = out.computeKey(i, j);
224 final double outValue =
225 out.entries.get(outKey) + value * m.entries.get(rightKey);
226 if (outValue == 0.0) {
227 out.entries.remove(outKey);
228 } else {
229 out.entries.put(outKey, outValue);
230 }
231 }
232 }
233 }
234
235 return out;
236 }
237
238
239 @Override
240 public double getEntry(int row, int column) throws OutOfRangeException {
241 MatrixUtils.checkRowIndex(this, row);
242 MatrixUtils.checkColumnIndex(this, column);
243 return entries.get(computeKey(row, column));
244 }
245
246
247 @Override
248 public int getRowDimension() {
249 return rows;
250 }
251
252
253 @Override
254 public void setEntry(int row, int column, double value)
255 throws OutOfRangeException {
256 MatrixUtils.checkRowIndex(this, row);
257 MatrixUtils.checkColumnIndex(this, column);
258 if (value == 0.0) {
259 entries.remove(computeKey(row, column));
260 } else {
261 entries.put(computeKey(row, column), value);
262 }
263 }
264
265
266 @Override
267 public void addToEntry(int row, int column, double increment)
268 throws OutOfRangeException {
269 MatrixUtils.checkRowIndex(this, row);
270 MatrixUtils.checkColumnIndex(this, column);
271 final int key = computeKey(row, column);
272 final double value = entries.get(key) + increment;
273 if (value == 0.0) {
274 entries.remove(key);
275 } else {
276 entries.put(key, value);
277 }
278 }
279
280
281 @Override
282 public void multiplyEntry(int row, int column, double factor)
283 throws OutOfRangeException {
284 MatrixUtils.checkRowIndex(this, row);
285 MatrixUtils.checkColumnIndex(this, column);
286 final int key = computeKey(row, column);
287 final double value = entries.get(key) * factor;
288 if (value == 0.0) {
289 entries.remove(key);
290 } else {
291 entries.put(key, value);
292 }
293 }
294
295
296
297
298
299
300
301 private int computeKey(int row, int column) {
302 return row * columns + column;
303 }
304
305 }