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;
25
26 import org.dishevelled.bitset.MutableBitSet;
27
28 import org.dishevelled.functor.BinaryProcedure;
29
30
31
32
33
34
35 public final class BitMatrix2D
36 {
37
38 private final MutableBitSet bitset;
39
40
41 private final long rows;
42
43
44 private final long columns;
45
46
47 private final long size;
48
49
50
51
52
53
54
55
56
57
58 public BitMatrix2D(final long rows, final long columns)
59 {
60 if (rows < 0)
61 {
62 throw new IllegalArgumentException("rows must be >= 0");
63 }
64 if (columns < 0)
65 {
66 throw new IllegalArgumentException("columns must be >= 0");
67 }
68 this.rows = rows;
69 this.columns = columns;
70 this.size = (rows * columns);
71 this.bitset = new MutableBitSet(this.size);
72 }
73
74
75
76
77
78
79
80 public long size()
81 {
82 return size;
83 }
84
85
86
87
88
89
90 public long rows()
91 {
92 return rows;
93 }
94
95
96
97
98
99
100 public long columns()
101 {
102 return columns;
103 }
104
105
106
107
108
109
110
111 public long cardinality()
112 {
113 return bitset.cardinality();
114 }
115
116
117
118
119
120
121 public boolean isEmpty()
122 {
123 return (0 == cardinality());
124 }
125
126
127
128
129 public void clear()
130 {
131 for (long i = bitset.nextSetBit(0); i >= 0; i = bitset.nextSetBit(i + 1))
132 {
133 bitset.clear(i);
134 }
135 }
136
137
138
139
140
141
142
143
144
145
146
147 public boolean get(final long row, final long column)
148 {
149 if (row < 0)
150 {
151 throw new IndexOutOfBoundsException(row + " < 0");
152 }
153 if (row >= rows)
154 {
155 throw new IndexOutOfBoundsException(row + " >= " + rows);
156 }
157 if (column < 0)
158 {
159 throw new IndexOutOfBoundsException(column + " < 0");
160 }
161 if (column >= columns)
162 {
163 throw new IndexOutOfBoundsException(column + " >= " + columns);
164 }
165 return getQuick(row, column);
166 }
167
168
169
170
171
172
173
174
175 public boolean getQuick(final long row, final long column)
176 {
177 return bitset.getQuick(index(row, column));
178 }
179
180
181
182
183
184
185
186
187
188
189
190 public void set(final long row, final long column, final boolean value)
191 {
192 if (row < 0)
193 {
194 throw new IndexOutOfBoundsException(row + " < 0");
195 }
196 if (row >= rows)
197 {
198 throw new IndexOutOfBoundsException(row + " >= " + rows);
199 }
200 if (column < 0)
201 {
202 throw new IndexOutOfBoundsException(column + " < 0");
203 }
204 if (column >= columns)
205 {
206 throw new IndexOutOfBoundsException(column + " >= " + columns);
207 }
208 setQuick(row, column, value);
209 }
210
211
212
213
214
215
216
217
218 public void setQuick(final long row, final long column, final boolean value)
219 {
220 long index = index(row, column);
221 if (value)
222 {
223 bitset.setQuick(index);
224 }
225 else
226 {
227 bitset.clearQuick(index);
228 }
229 }
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251 public void set(final long row0, final long column0,
252 final long row1, final long column1, final boolean value)
253 {
254 if (row0 < 0)
255 {
256 throw new IndexOutOfBoundsException(row0 + " < 0");
257 }
258 if (row0 >= rows)
259 {
260 throw new IndexOutOfBoundsException(row0 + " >= " + rows);
261 }
262 if (column0 < 0)
263 {
264 throw new IndexOutOfBoundsException(column0 + " < 0");
265 }
266 if (column0 >= columns)
267 {
268 throw new IndexOutOfBoundsException(column0 + " >= " + columns);
269 }
270 if (row1 < 0)
271 {
272 throw new IndexOutOfBoundsException(row1 + " < 0");
273 }
274 if (row1 > rows)
275 {
276 throw new IndexOutOfBoundsException(row1 + " > " + rows);
277 }
278 if (column1 < 0)
279 {
280 throw new IndexOutOfBoundsException(column1 + " < 0");
281 }
282 if (column1 > columns)
283 {
284 throw new IndexOutOfBoundsException(column1 + " > " + columns);
285 }
286
287 for (long row = row0; row < row1; row++)
288 {
289 for (long column = column0; column < column1; column++)
290 {
291 setQuick(row, column, value);
292 }
293 }
294 }
295
296
297
298
299
300
301
302
303
304
305
306 public void flip(final long row, final long column)
307 {
308 if (row < 0)
309 {
310 throw new IndexOutOfBoundsException(row + " < 0");
311 }
312 if (row >= rows)
313 {
314 throw new IndexOutOfBoundsException(row + " >= " + rows);
315 }
316 if (column < 0)
317 {
318 throw new IndexOutOfBoundsException(column + " < 0");
319 }
320 if (column >= columns)
321 {
322 throw new IndexOutOfBoundsException(column + " >= " + columns);
323 }
324 flipQuick(row, column);
325 }
326
327
328
329
330
331
332
333
334 public void flipQuick(final long row, final long column)
335 {
336 bitset.flipQuick(index(row, column));
337 }
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359 public void flip(final long row0, final long column0,
360 final long row1, final long column1)
361 {
362 if (row0 < 0)
363 {
364 throw new IndexOutOfBoundsException(row0 + " < 0");
365 }
366 if (row0 >= rows)
367 {
368 throw new IndexOutOfBoundsException(row0 + " >= " + rows);
369 }
370 if (column0 < 0)
371 {
372 throw new IndexOutOfBoundsException(column0 + " < 0");
373 }
374 if (column0 >= columns)
375 {
376 throw new IndexOutOfBoundsException(column0 + " >= " + columns);
377 }
378 if (row1 < 0)
379 {
380 throw new IndexOutOfBoundsException(row1 + " < 0");
381 }
382 if (row1 > rows)
383 {
384 throw new IndexOutOfBoundsException(row1 + " > " + rows);
385 }
386 if (column1 < 0)
387 {
388 throw new IndexOutOfBoundsException(column1 + " < 0");
389 }
390 if (column1 > columns)
391 {
392 throw new IndexOutOfBoundsException(column1 + " > " + columns);
393 }
394
395 for (long row = row0; row < row1; row++)
396 {
397 for (long column = column0; column < column1; column++)
398 {
399 flipQuick(row, column);
400 }
401 }
402 }
403
404
405
406
407
408
409
410 public BitMatrix2D assign(final boolean value)
411 {
412 if (size > 0)
413 {
414 set(0, 0, rows, columns, value);
415 }
416 return this;
417 }
418
419
420
421
422
423
424
425
426
427
428 public boolean intersects(final BitMatrix2D other)
429 {
430 if (other == null)
431 {
432 throw new IllegalArgumentException("other must not be null");
433 }
434 if ((size != other.size()) || (rows != other.rows()) || (columns != other.columns()))
435 {
436 throw new IllegalArgumentException("this and other must have the same dimensions");
437 }
438 return bitset.intersects(other.bitset);
439 }
440
441
442
443
444
445
446
447
448
449 public BitMatrix2D and(final BitMatrix2D other)
450 {
451 if (other == null)
452 {
453 throw new IllegalArgumentException("other must not be null");
454 }
455 if ((size != other.size()) || (rows != other.rows()) || (columns != other.columns()))
456 {
457 throw new IllegalArgumentException("this and other must have the same dimensions");
458 }
459 bitset.and(other.bitset);
460 return this;
461 }
462
463
464
465
466
467
468
469
470
471 public BitMatrix2D andNot(final BitMatrix2D other)
472 {
473 if (other == null)
474 {
475 throw new IllegalArgumentException("other must not be null");
476 }
477 if ((size != other.size()) || (rows != other.rows()) || (columns != other.columns()))
478 {
479 throw new IllegalArgumentException("this and other must have the same dimensions");
480 }
481 bitset.andNot(other.bitset);
482 return this;
483 }
484
485
486
487
488
489
490
491
492
493 public BitMatrix2D or(final BitMatrix2D other)
494 {
495 if (other == null)
496 {
497 throw new IllegalArgumentException("other must not be null");
498 }
499 if ((size != other.size()) || (rows != other.rows()) || (columns != other.columns()))
500 {
501 throw new IllegalArgumentException("this and other must have the same dimensions");
502 }
503 bitset.or(other.bitset);
504 return this;
505 }
506
507
508
509
510
511
512
513
514
515 public BitMatrix2D xor(final BitMatrix2D other)
516 {
517 if (other == null)
518 {
519 throw new IllegalArgumentException("other must not be null");
520 }
521 if ((size != other.size()) || (rows != other.rows()) || (columns != other.columns()))
522 {
523 throw new IllegalArgumentException("this and other must have the same dimensions");
524 }
525 bitset.xor(other.bitset);
526 return this;
527 }
528
529
530
531
532
533
534
535
536 public void forEach(final boolean value, final BinaryProcedure<Long, Long> procedure)
537 {
538 if (procedure == null)
539 {
540 throw new IllegalArgumentException("procedure must not be null");
541 }
542
543 for (long row = 0; row < rows; row++)
544 {
545 for (long column = 0; column < columns; column++)
546 {
547 if (getQuick(row, column) == value)
548 {
549 procedure.run(Long.valueOf(row), Long.valueOf(column));
550 }
551 }
552 }
553 }
554
555
556 public boolean equals(final Object o)
557 {
558 if (o == null)
559 {
560 return false;
561 }
562 if (!(o instanceof BitMatrix2D))
563 {
564 return false;
565 }
566
567 BitMatrix2D bm = (BitMatrix2D) o;
568
569 if ((size != bm.size()) || (rows != bm.rows()) || (columns != bm.columns()))
570 {
571 return false;
572 }
573 return bitset.equals(bm.bitset);
574 }
575
576
577 public int hashCode()
578 {
579 int hashCode = 37;
580 hashCode = 17 * hashCode + (int) (size ^ (size >>> 32));
581 hashCode = 17 * hashCode + (int) (rows ^ (rows >>> 32));
582 hashCode = 17 * hashCode + (int) (columns ^ (columns >>> 32));
583 hashCode = 17 * hashCode + bitset.hashCode();
584 return hashCode;
585 }
586
587
588
589
590
591
592
593
594 private long index(final long row, final long column)
595 {
596 return (columns * row) + column;
597 }
598 }