1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.dishevelled.matrix.impl;
25
26 import java.io.IOException;
27 import java.io.Serializable;
28 import java.io.ObjectInputStream;
29 import java.io.ObjectOutputStream;
30
31 import java.util.Map;
32 import java.util.HashMap;
33
34 import org.dishevelled.functor.UnaryProcedure;
35
36 import org.dishevelled.matrix.Matrix1D;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 public class SparseMatrix2D<E>
52 extends AbstractMatrix2D<E>
53 implements Serializable
54 {
55
56 private Map<Long, E> elements;
57
58
59 private static final float DEFAULT_LOAD_FACTOR = 0.75f;
60
61
62
63
64
65 private SparseMatrix2D()
66 {
67 elements = null;
68 }
69
70
71
72
73
74
75
76
77
78
79 public SparseMatrix2D(final long rows, final long columns)
80 {
81 this(rows,
82 columns,
83 (int) Math.min(Integer.MAX_VALUE, ((rows * columns) * DEFAULT_LOAD_FACTOR)),
84 DEFAULT_LOAD_FACTOR);
85 }
86
87
88
89
90
91
92
93
94
95
96 public SparseMatrix2D(final long rows, final long columns, final int initialCapacity, final float loadFactor)
97 {
98 super(rows, columns);
99 elements = new HashMap<Long, E>(initialCapacity, loadFactor);
100 }
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116 protected SparseMatrix2D(final long rows,
117 final long columns,
118 final long rowZero,
119 final long columnZero,
120 final long rowStride,
121 final long columnStride,
122 final boolean isView,
123 final Map<Long, E> elements)
124 {
125 super(rows, columns,
126 rowZero, columnZero,
127 rowStride, columnStride, isView);
128 this.elements = elements;
129 }
130
131
132
133 public Object clone()
134 {
135 return new SparseMatrix2D<E>(rows, columns,
136 rowZero, columnZero,
137 rowStride, columnStride,
138 isView, elements);
139 }
140
141
142 public E getQuick(final long row, final long column)
143 {
144 long index = rowZero + (row * rowStride) + columnZero + (column * columnStride);
145 return elements.get(index);
146 }
147
148
149 public void setQuick(final long row, final long column, final E e)
150 {
151 long index = rowZero + (row * rowStride) + columnZero + (column * columnStride);
152 if (e == null)
153 {
154 elements.remove(index);
155 }
156 else
157 {
158 elements.put(index, e);
159 }
160 }
161
162
163
164
165
166
167 public void clear()
168 {
169 if (isView)
170 {
171 super.clear();
172 }
173 else
174 {
175 elements.clear();
176 }
177 }
178
179
180
181
182
183
184 public void forEachNonNull(final UnaryProcedure<? super E> procedure)
185 {
186 if (isView)
187 {
188 super.forEachNonNull(procedure);
189 }
190 else
191 {
192 if (procedure == null)
193 {
194 throw new IllegalArgumentException("procedure must not be null");
195 }
196
197 for (E e : elements.values())
198 {
199 procedure.run(e);
200 }
201 }
202 }
203
204
205 public Matrix1D<E> viewRow(final long row)
206 {
207 if (row < 0)
208 {
209 throw new IndexOutOfBoundsException(row + " < 0");
210 }
211 if (row >= rows)
212 {
213 throw new IndexOutOfBoundsException(row + " >= " + rows);
214 }
215 return new RowView(row);
216 }
217
218
219 public Matrix1D<E> viewColumn(final long column)
220 {
221 if (column < 0)
222 {
223 throw new IndexOutOfBoundsException(column + " < 0");
224 }
225 if (column >= columns)
226 {
227 throw new IndexOutOfBoundsException(column + " >= " + columns);
228 }
229 return new ColumnView(column);
230 }
231
232
233
234
235
236
237 protected Map<Long, E> elements()
238 {
239 return elements;
240 }
241
242
243
244
245
246
247
248
249 private void writeObject(final ObjectOutputStream out)
250 throws IOException
251 {
252 out.writeLong(rows);
253 out.writeLong(columns);
254 out.writeLong(rowZero);
255 out.writeLong(columnZero);
256 out.writeLong(rowStride);
257 out.writeLong(columnStride);
258 out.writeBoolean(isView);
259 out.writeObject(elements);
260 }
261
262
263
264
265
266
267
268
269
270 private void readObject(final ObjectInputStream in)
271 throws IOException, ClassNotFoundException
272 {
273 super.rows = in.readLong();
274 super.columns = in.readLong();
275 super.rowZero = in.readLong();
276 super.columnZero = in.readLong();
277 super.rowStride = in.readLong();
278 super.columnStride = in.readLong();
279 super.isView = in.readBoolean();
280 this.elements = (Map<Long, E>) in.readObject();
281 }
282
283
284 public String toString()
285 {
286 StringBuffer sb = new StringBuffer(super.toString());
287 sb.append("\n rows=");
288 sb.append(rows);
289 sb.append(" columns=");
290 sb.append(columns);
291 sb.append(" rowZero=");
292 sb.append(rowZero);
293 sb.append(" columnZero=");
294 sb.append(columnZero);
295 sb.append(" rowStride=");
296 sb.append(rowStride);
297 sb.append(" columnStride=");
298 sb.append(columnStride);
299 sb.append("\n elements=");
300 sb.append(elements.toString());
301 sb.append("\n");
302 return sb.toString();
303 }
304
305
306
307
308 private class RowView
309 extends SparseMatrix1D<E>
310 {
311
312
313
314
315
316
317 RowView(final long row)
318 {
319 super(SparseMatrix2D.this.columns,
320 SparseMatrix2D.this.rowZero
321 + (row * SparseMatrix2D.this.rowStride)
322 + SparseMatrix2D.this.columnZero,
323 SparseMatrix2D.this.columnStride,
324 true,
325 elements);
326 }
327 }
328
329
330
331
332 private class ColumnView
333 extends SparseMatrix1D<E>
334 {
335
336
337
338
339
340
341 ColumnView(final long column)
342 {
343 super(SparseMatrix2D.this.rows,
344 SparseMatrix2D.this.rowZero
345 + (column * SparseMatrix2D.this.columnStride)
346 + SparseMatrix2D.this.columnZero,
347 SparseMatrix2D.this.rowStride,
348 true,
349 elements);
350 }
351 }
352 }