IT++ Logo
gf2mat.cpp
Go to the documentation of this file.
1
29#include <itpp/base/gf2mat.h>
30#include <itpp/base/specmat.h>
31#include <itpp/base/matfunc.h>
33#include <iostream>
34
35namespace itpp
36{
37
38// ====== IMPLEMENTATION OF THE ALIST CLASS ==========
39
41 : data_ok(false)
42{
43 read(fname);
44}
45
46void GF2mat_sparse_alist::read(const std::string &fname)
47{
48 std::ifstream file;
49 std::string line;
50 std::stringstream ss;
51
52 file.open(fname.c_str());
53 it_assert(file.is_open(),
54 "GF2mat_sparse_alist::read(): Could not open file \""
55 << fname << "\" for reading");
56
57 // parse N and M:
58 getline(file, line);
59 ss << line;
60 ss >> N >> M;
61 it_assert(!ss.fail(),
62 "GF2mat_sparse_alist::read(): Wrong alist data (N or M)");
63 it_assert((N > 0) && (M > 0),
64 "GF2mat_sparse_alist::read(): Wrong alist data");
65 ss.seekg(0, std::ios::end);
66 ss.clear();
67
68 // parse max_num_n and max_num_m
69 getline(file, line);
70 ss << line;
71 ss >> max_num_n >> max_num_m;
72 it_assert(!ss.fail(),
73 "GF2mat_sparse_alist::read(): Wrong alist data (max_num_{n,m})");
74 it_assert((max_num_n >= 0) && (max_num_n <= N) &&
75 (max_num_m >= 0) && (max_num_m <= M),
76 "GF2mat_sparse_alist::read(): Wrong alist data");
77 ss.seekg(0, std::ios::end);
78 ss.clear();
79
80 // parse weight of each column n
81 num_nlist.set_size(N);
82 num_nlist.clear();
83 getline(file, line);
84 ss << line;
85 for (int i = 0; i < N; i++) {
86 ss >> num_nlist(i);
87 it_assert(!ss.fail(),
88 "GF2mat_sparse_alist::read(): Wrong alist data (num_nlist("
89 << i << "))");
90 it_assert((num_nlist(i) >= 0) && (num_nlist(i) <= M),
91 "GF2mat_sparse_alist::read(): Wrong alist data (num_nlist("
92 << i << "))");
93 }
94 ss.seekg(0, std::ios::end);
95 ss.clear();
96
97 // parse weight of each row m
98 num_mlist.set_size(M);
99 num_mlist.clear();
100 getline(file, line);
101 ss << line;
102 for (int i = 0; i < M; i++) {
103 ss >> num_mlist(i);
104 it_assert(!ss.fail(),
105 "GF2mat_sparse_alist::read(): Wrong alist data (num_mlist("
106 << i << "))");
107 it_assert((num_mlist(i) >= 0) && (num_mlist(i) <= N),
108 "GF2mat_sparse_alist::read(): Wrong alist data (num_mlist("
109 << i << "))");
110 }
111 ss.seekg(0, std::ios::end);
112 ss.clear();
113
114 // parse coordinates in the n direction with non-zero entries
115 nlist.set_size(N, max_num_n);
116 nlist.clear();
117 for (int i = 0; i < N; i++) {
118 getline(file, line);
119 ss << line;
120 for (int j = 0; j < num_nlist(i); j++) {
121 ss >> nlist(i, j);
122 it_assert(!ss.fail(),
123 "GF2mat_sparse_alist::read(): Wrong alist data (nlist("
124 << i << "," << j << "))");
125 it_assert((nlist(i, j) > 0) && (nlist(i, j) <= M),
126 "GF2mat_sparse_alist::read(): Wrong alist data (nlist("
127 << i << "," << j << "))");
128 }
129 ss.seekg(0, std::ios::end);
130 ss.clear();
131 }
132
133 // parse coordinates in the m direction with non-zero entries
134 mlist.set_size(M, max_num_m);
135 mlist.clear();
136 for (int i = 0; i < M; i++) {
137 getline(file, line);
138 ss << line;
139 for (int j = 0; j < num_mlist(i); j++) {
140 ss >> mlist(i, j);
141 it_assert(!ss.fail(),
142 "GF2mat_sparse_alist::read(): Wrong alist data (mlist("
143 << i << "," << j << "))");
144 it_assert((mlist(i, j) > 0) && (mlist(i, j) <= N),
145 "GF2mat_sparse_alist::read(): Wrong alist data (mlist("
146 << i << "," << j << "))");
147 }
148 ss.seekg(0, std::ios::end);
149 ss.clear();
150 }
151
152 file.close();
153 data_ok = true;
154}
155
156void GF2mat_sparse_alist::write(const std::string &fname) const
157{
159 "GF2mat_sparse_alist::write(): alist data not ready for writing");
160
161 std::ofstream file(fname.c_str(), std::ofstream::out);
162 it_assert(file.is_open(),
163 "GF2mat_sparse_alist::write(): Could not open file \""
164 << fname << "\" for writing");
165
166 file << N << " " << M << std::endl;
167 file << max_num_n << " " << max_num_m << std::endl;
168
169 for (int i = 0; i < num_nlist.length() - 1; i++)
170 file << num_nlist(i) << " ";
171 file << num_nlist(num_nlist.length() - 1) << std::endl;
172
173 for (int i = 0; i < num_mlist.length() - 1; i++)
174 file << num_mlist(i) << " ";
175 file << num_mlist(num_mlist.length() - 1) << std::endl;
176
177 for (int i = 0; i < N; i++) {
178 for (int j = 0; j < num_nlist(i) - 1; j++)
179 file << nlist(i, j) << " ";
180 file << nlist(i, num_nlist(i) - 1) << std::endl;
181 }
182
183 for (int i = 0; i < M; i++) {
184 for (int j = 0; j < num_mlist(i) - 1; j++)
185 file << mlist(i, j) << " ";
186 file << mlist(i, num_mlist(i) - 1) << std::endl;
187 }
188
189 file.close();
190}
191
192
194{
195 GF2mat_sparse sbmat(M, N, max_num_m);
196
197 for (int i = 0; i < M; i++) {
198 for (int j = 0; j < num_mlist(i); j++) {
199 sbmat.set_new(i, mlist(i, j) - 1, bin(1));
200 }
201 }
202 sbmat.compact();
203
204 if (transpose) {
205 return sbmat.transpose();
206 }
207 else {
208 return sbmat;
209 }
210}
211
212
213// ----------------------------------------------------------------------
214// WARNING: This method is very slow. Sparse_Mat has to be extended with
215// some extra functions to improve the performance of this.
216// ----------------------------------------------------------------------
218 bool transpose)
219{
220 if (transpose) {
221 from_sparse(sbmat.transpose(), false);
222 }
223 else {
224 // check matrix dimension
225 M = sbmat.rows();
226 N = sbmat.cols();
227
228 num_mlist.set_size(M);
229 num_nlist.set_size(N);
230
231 // fill mlist matrix, num_mlist vector and max_num_m
232 mlist.set_size(0, 0);
233 int tmp_cols = 0; // initial number of allocated columns
234 for (int i = 0; i < M; i++) {
235 ivec temp_row(0);
236 for (int j = 0; j < N; j++) {
237 if (sbmat(i, j) == bin(1)) {
238 temp_row = concat(temp_row, j + 1);
239 }
240 }
241 int trs = temp_row.size();
242 if (trs > tmp_cols) {
243 tmp_cols = trs;
244 mlist.set_size(M, tmp_cols, true);
245 }
246 else if (trs < tmp_cols) {
247 temp_row.set_size(tmp_cols, true);
248 }
249 mlist.set_row(i, temp_row);
250 num_mlist(i) = trs;
251 }
253
254 // fill nlist matrix, num_nlist vector and max_num_n
255 nlist.set_size(0, 0);
256 tmp_cols = 0; // initial number of allocated columns
257 for (int j = 0; j < N; j++) {
258 ivec temp_row = sbmat.get_col(j).get_nz_indices() + 1;
259 int trs = temp_row.size();
260 if (trs > tmp_cols) {
261 tmp_cols = trs;
262 nlist.set_size(N, tmp_cols, true);
263 }
264 else if (trs < tmp_cols) {
265 temp_row.set_size(tmp_cols, true);
266 }
267 nlist.set_row(j, temp_row);
268 num_nlist(j) = trs;
269 }
271
272 data_ok = true;
273 }
274}
275
276
277// ----------------------------------------------------------------------
278// Implementation of a dense GF2 matrix class
279// ----------------------------------------------------------------------
280
281GF2mat::GF2mat(int i, int j): nrows(i), ncols(j),
282 nwords((j >> shift_divisor) + 1)
283{
284 data.set_size(nrows, nwords);
285 data.clear();
286}
287
288GF2mat::GF2mat(): nrows(1), ncols(1), nwords(1)
289{
290 data.set_size(nrows, nwords);
291 data.clear();
292}
293
294GF2mat::GF2mat(const bvec &x, bool is_column)
295{
296 if (is_column) { // create column vector
297 nrows = length(x);
298 ncols = 1;
299 nwords = 1;
300 data.set_size(nrows, nwords);
301 data.clear();
302 for (int i = 0; i < nrows; i++) {
303 set(i, 0, x(i));
304 }
305 }
306 else { // create row vector
307 nrows = 1;
308 ncols = length(x);
309 nwords = (ncols >> shift_divisor) + 1;
310 data.set_size(nrows, nwords);
311 data.clear();
312 for (int i = 0; i < ncols; i++) {
313 set(0, i, x(i));
314 }
315 }
316}
317
318
319GF2mat::GF2mat(const bmat &X): nrows(X.rows()), ncols(X.cols())
320{
321 nwords = (ncols >> shift_divisor) + 1;
322 data.set_size(nrows, nwords);
323 data.clear();
324 for (int i = 0; i < nrows; i++) {
325 for (int j = 0; j < ncols; j++) {
326 set(i, j, X(i, j));
327 }
328 }
329}
330
331
333{
334 nrows = X.rows();
335 ncols = X.cols();
336 nwords = (ncols >> shift_divisor) + 1;
337 data.set_size(nrows, nwords);
338 for (int i = 0; i < nrows; i++) {
339 for (int j = 0; j < nwords; j++) {
340 data(i, j) = 0;
341 }
342 }
343
344 for (int j = 0; j < ncols; j++) {
345 for (int i = 0; i < X.get_col(j).nnz(); i++) {
346 bin b = X.get_col(j).get_nz_data(i);
347 set(X.get_col(j).get_nz_index(i), j, b);
348 }
349 }
350}
351
352GF2mat::GF2mat(const GF2mat_sparse &X, int m1, int n1, int m2, int n2)
353{
354 it_assert(X.rows() > m2, "GF2mat(): indexes out of range");
355 it_assert(X.cols() > n2, "GF2mat(): indexes out of range");
356 it_assert(m1 >= 0 && n1 >= 0 && m2 >= m1 && n2 >= n1,
357 "GF2mat::GF2mat(): indexes out of range");
358
359 nrows = m2 - m1 + 1;
360 ncols = n2 - n1 + 1;
361 nwords = (ncols >> shift_divisor) + 1;
362 data.set_size(nrows, nwords);
363
364 for (int i = 0; i < nrows; i++) {
365 for (int j = 0; j < nwords; j++) {
366 data(i, j) = 0;
367 }
368 }
369
370 for (int i = 0; i < nrows; i++) {
371 for (int j = 0; j < ncols; j++) {
372 bin b = X(i + m1, j + n1);
373 set(i, j, b);
374 }
375 }
376}
377
378
379GF2mat::GF2mat(const GF2mat_sparse &X, const ivec &columns)
380{
381 it_assert(X.cols() > max(columns),
382 "GF2mat::GF2mat(): index out of range");
383 it_assert(min(columns) >= 0,
384 "GF2mat::GF2mat(): column index must be positive");
385
386 nrows = X.rows();
387 ncols = length(columns);
388 nwords = (ncols >> shift_divisor) + 1;
389 data.set_size(nrows, nwords);
390
391 for (int i = 0; i < nrows; i++) {
392 for (int j = 0; j < nwords; j++) {
393 data(i, j) = 0;
394 }
395 }
396
397 for (int j = 0; j < ncols; j++) {
398 for (int i = 0; i < X.get_col(columns(j)).nnz(); i++) {
399 bin b = X.get_col(columns(j)).get_nz_data(i);
400 set(X.get_col(columns(j)).get_nz_index(i), j, b);
401 }
402 }
403}
404
405
406void GF2mat::set_size(int m, int n, bool copy)
407{
408 nrows = m;
409 ncols = n;
410 nwords = (ncols >> shift_divisor) + 1;
411 data.set_size(nrows, nwords, copy);
412 if (!copy)
413 data.clear();
414}
415
416
418{
419 GF2mat_sparse Z(nrows, ncols);
420 for (int i = 0; i < nrows; i++) {
421 for (int j = 0; j < ncols; j++) {
422 if (get(i, j) == 1) {
423 Z.set(i, j, 1);
424 }
425 }
426 }
427
428 return Z;
429}
430
431bvec GF2mat::bvecify() const
432{
433 it_assert(nrows == 1 || ncols == 1,
434 "GF2mat::bvecify() matrix must be a vector");
435 int n = (nrows == 1 ? ncols : nrows);
436 bvec result(n);
437 if (nrows == 1) {
438 for (int i = 0; i < n; i++) {
439 result(i) = get(0, i);
440 }
441 }
442 else {
443 for (int i = 0; i < n; i++) {
444 result(i) = get(i, 0);
445 }
446 }
447 return result;
448}
449
450
451void GF2mat::set_row(int i, bvec x)
452{
453 it_assert(length(x) == ncols,
454 "GF2mat::set_row(): dimension mismatch");
455 for (int j = 0; j < ncols; j++) {
456 set(i, j, x(j));
457 }
458}
459
460void GF2mat::set_col(int j, bvec x)
461{
462 it_assert(length(x) == nrows,
463 "GF2mat::set_col(): dimension mismatch");
464 for (int i = 0; i < nrows; i++) {
465 set(i, j, x(i));
466 }
467}
468
469
471{
472 GF2mat Z(m, m);
473 for (int i = 0; i < m; i++) {
474 Z.set(i, i, 1);
475 }
476 return Z;
477}
478
479GF2mat GF2mat::get_submatrix(int m1, int n1, int m2, int n2) const
480{
481 it_assert(m1 >= 0 && n1 >= 0 && m2 >= m1 && n2 >= n1
482 && m2 < nrows && n2 < ncols,
483 "GF2mat::get_submatrix() index out of range");
484 GF2mat result(m2 - m1 + 1, n2 - n1 + 1);
485
486 for (int i = m1; i <= m2; i++) {
487 for (int j = n1; j <= n2; j++) {
488 result.set(i - m1, j - n1, get(i, j));
489 }
490 }
491
492 return result;
493}
494
495
497{
498 it_assert(X.ncols == ncols,
499 "GF2mat::concatenate_vertical(): dimension mismatch");
500 it_assert(X.nwords == nwords,
501 "GF2mat::concatenate_vertical(): dimension mismatch");
502
503 GF2mat result(nrows + X.nrows, ncols);
504 for (int i = 0; i < nrows; i++) {
505 for (int j = 0; j < nwords; j++) {
506 result.data(i, j) = data(i, j);
507 }
508 }
509
510 for (int i = 0; i < X.nrows; i++) {
511 for (int j = 0; j < nwords; j++) {
512 result.data(i + nrows, j) = X.data(i, j);
513 }
514 }
515
516 return result;
517}
518
520{
521 it_assert(X.nrows == nrows,
522 "GF2mat::concatenate_horizontal(): dimension mismatch");
523
524 GF2mat result(nrows, X.ncols + ncols);
525 for (int i = 0; i < nrows; i++) {
526 for (int j = 0; j < ncols; j++) {
527 result.set(i, j, get(i, j));
528 }
529 }
530
531 for (int i = 0; i < nrows; i++) {
532 for (int j = 0; j < X.ncols; j++) {
533 result.set(i, j + ncols, X.get(i, j));
534 }
535 }
536
537 return result;
538}
539
540bvec GF2mat::get_row(int i) const
541{
542 bvec result(ncols);
543 for (int j = 0; j < ncols; j++) {
544 result(j) = get(i, j);
545 }
546
547 return result;
548}
549
550bvec GF2mat::get_col(int j) const
551{
552 bvec result(nrows);
553 for (int i = 0; i < nrows; i++) {
554 result(i) = get(i, j);
555 }
556
557 return result;
558}
559
560
561int GF2mat::T_fact(GF2mat &T, GF2mat &U, ivec &perm) const
562{
563 T = gf2dense_eye(nrows);
564 U = *this;
565
566 perm = zeros_i(ncols);
567 for (int i = 0; i < ncols; i++) {
568 perm(i) = i;
569 }
570
571 if (nrows > 250) { // avoid cluttering output ...
572 it_info_debug("Performing T-factorization of GF(2) matrix... rows: "
573 << nrows << " cols: " << ncols << " .... " << std::endl);
574 }
575 int pdone = 0;
576 for (int j = 0; j < nrows; j++) {
577 // Now working on diagonal element j,j
578 // First try find a row with a 1 in column i
579 int i1, j1;
580 for (i1 = j; i1 < nrows; i1++) {
581 for (j1 = j; j1 < ncols; j1++) {
582 if (U.get(i1, j1) == 1) { goto found; }
583 }
584 }
585
586 return j;
587
588 found:
589 U.swap_rows(i1, j);
590 T.swap_rows(i1, j);
591 U.swap_cols(j1, j);
592
593 int temp = perm(j);
594 perm(j) = perm(j1);
595 perm(j1) = temp;
596
597 // now subtract row i from remaining rows
598 for (int i1 = j + 1; i1 < nrows; i1++) {
599 if (U.get(i1, j) == 1) {
600 int ptemp = floor_i(100.0 * (i1 + j * nrows) / (nrows * nrows));
601 if (nrows > 250 && ptemp > pdone + 10) {
602 it_info_debug(ptemp << "% done.");
603 pdone = ptemp;
604 }
605 U.add_rows(i1, j);
606 T.add_rows(i1, j);
607 }
608 }
609 }
610 return nrows;
611}
612
613
615 ivec &perm, int rank,
616 int r, int c) const
617{
618 // First, update U (before re-triangulization)
619 int c0 = c;
620 for (c = 0; c < ncols; c++) {
621 if (perm(c) == c0) {
622 goto foundidx;
623 }
624 }
625 it_error("GF2mat::T_fact_update_bitflip() - internal error");
626
627foundidx:
628 for (int i = 0; i < nrows; i++) {
629 if (T.get(i, r) == 1) {
630 U.addto_element(i, c, 1);
631 }
632 }
633
634 // first move column c to the end
635 bvec lastcol = U.get_col(c);
636 int temp_perm = perm(c);
637 for (int j = c; j < ncols - 1; j++) {
638 U.set_col(j, U.get_col(j + 1));
639 perm(j) = perm(j + 1);
640 }
641 U.set_col(ncols - 1, lastcol);
642 perm(ncols - 1) = temp_perm;
643
644 // then, if the matrix is tall, also move row c to the end
645 if (nrows >= ncols) {
646 bvec lastrow_U = U.get_row(c);
647 bvec lastrow_T = T.get_row(c);
648 for (int i = c; i < nrows - 1; i++) {
649 U.set_row(i, U.get_row(i + 1));
650 T.set_row(i, T.get_row(i + 1));
651 }
652 U.set_row(nrows - 1, lastrow_U);
653 T.set_row(nrows - 1, lastrow_T);
654
655 // Do Gaussian elimination on the last row
656 for (int j = c; j < ncols; j++) {
657 if (U.get(nrows - 1, j) == 1) {
658 U.add_rows(nrows - 1, j);
659 T.add_rows(nrows - 1, j);
660 }
661 }
662 }
663
664 // Now, continue T-factorization from the point (rank-1,rank-1)
665 for (int j = rank - 1; j < nrows; j++) {
666 int i1, j1;
667 for (i1 = j; i1 < nrows; i1++) {
668 for (j1 = j; j1 < ncols; j1++) {
669 if (U.get(i1, j1) == 1) {
670 goto found;
671 }
672 }
673 }
674
675 return j;
676
677 found:
678 U.swap_rows(i1, j);
679 T.swap_rows(i1, j);
680 U.swap_cols(j1, j);
681
682 int temp = perm(j);
683 perm(j) = perm(j1);
684 perm(j1) = temp;
685
686 for (int i1 = j + 1; i1 < nrows; i1++) {
687 if (U.get(i1, j) == 1) {
688 U.add_rows(i1, j);
689 T.add_rows(i1, j);
690 }
691 }
692 }
693
694 return nrows;
695}
696
698 ivec &perm, bvec newcol) const
699{
700 int i0 = T.rows();
701 int j0 = U.cols();
702 it_assert(j0 > 0, "GF2mat::T_fact_update_addcol(): dimension mismatch");
703 it_assert(i0 == T.cols(),
704 "GF2mat::T_fact_update_addcol(): dimension mismatch");
705 it_assert(i0 == U.rows(),
706 "GF2mat::T_fact_update_addcol(): dimension mismatch");
707 it_assert(length(perm) == j0,
708 "GF2mat::T_fact_update_addcol(): dimension mismatch");
709 it_assert(U.get(j0 - 1, j0 - 1) == 1,
710 "GF2mat::T_fact_update_addcol(): dimension mismatch");
711 // The following test is VERY TIME-CONSUMING
712 it_assert_debug(U.row_rank() == j0,
713 "GF2mat::T_fact_update_addcol(): factorization has incorrect rank");
714
715 bvec z = T * newcol;
716 GF2mat Utemp = U.concatenate_horizontal(GF2mat(z, 1));
717
718 // start working on position (j0,j0)
719 int i;
720 for (i = j0; i < i0; i++) {
721 if (Utemp.get(i, j0) == 1) {
722 goto found;
723 }
724 }
725 return (false); // adding the new column would not improve the rank
726
727found:
728 perm.set_length(j0 + 1, true);
729 perm(j0) = j0;
730
731 Utemp.swap_rows(i, j0);
732 T.swap_rows(i, j0);
733
734 for (int i1 = j0 + 1; i1 < i0; i1++) {
735 if (Utemp.get(i1, j0) == 1) {
736 Utemp.add_rows(i1, j0);
737 T.add_rows(i1, j0);
738 }
739 }
740
741 U = Utemp;
742 return (true); // the new column was successfully added
743}
744
745
746
747
749{
750 it_assert(nrows == ncols, "GF2mat::inverse(): Matrix must be square");
751
752 // first compute the T-factorization
753 GF2mat T, U;
754 ivec perm;
755 int rank = T_fact(T, U, perm);
756 it_assert(rank == ncols, "GF2mat::inverse(): Matrix is not full rank");
757
758 // backward substitution
759 for (int i = ncols - 2; i >= 0; i--) {
760 for (int j = ncols - 1; j > i; j--) {
761 if (U.get(i, j) == 1) {
762 U.add_rows(i, j);
763 T.add_rows(i, j);
764 }
765 }
766 }
767 T.permute_rows(perm, 1);
768 return T;
769}
770
772{
773 GF2mat T, U;
774 ivec perm;
775 int rank = T_fact(T, U, perm);
776 return rank;
777}
778
779bool GF2mat::is_zero() const
780{
781 for (int i = 0; i < nrows; i++) {
782 for (int j = 0; j < nwords; j++) {
783 if (data(i, j) != 0) {
784 return false;
785 }
786 }
787 }
788 return true;
789}
790
791bool GF2mat::operator==(const GF2mat &X) const
792{
793 if (X.nrows != nrows) { return false; }
794 if (X.ncols != ncols) { return false; }
795 it_assert(X.nwords == nwords, "GF2mat::operator==() dimension mismatch");
796
797 for (int i = 0; i < nrows; i++) {
798 for (int j = 0; j < nwords; j++) {
799 // if (X.get(i,j)!=get(i,j)) {
800 if (X.data(i, j) != data(i, j)) {
801 return false;
802 }
803 }
804 }
805 return true;
806}
807
808
809void GF2mat::add_rows(int i, int j)
810{
811 it_assert(i >= 0 && i < nrows, "GF2mat::add_rows(): out of range");
812 it_assert(j >= 0 && j < nrows, "GF2mat::add_rows(): out of range");
813 for (int k = 0; k < nwords; k++) {
814 data(i, k) ^= data(j, k);
815 }
816}
817
818void GF2mat::swap_rows(int i, int j)
819{
820 it_assert(i >= 0 && i < nrows, "GF2mat::swap_rows(): index out of range");
821 it_assert(j >= 0 && j < nrows, "GF2mat::swap_rows(): index out of range");
822 for (int k = 0; k < nwords; k++) {
823 unsigned char temp = data(i, k);
824 data(i, k) = data(j, k);
825 data(j, k) = temp;
826 }
827}
828
829void GF2mat::swap_cols(int i, int j)
830{
831 it_assert(i >= 0 && i < ncols, "GF2mat::swap_cols(): index out of range");
832 it_assert(j >= 0 && j < ncols, "GF2mat::swap_cols(): index out of range");
833 bvec temp = get_col(i);
834 set_col(i, get_col(j));
835 set_col(j, temp);
836}
837
838
840{
841 nrows = X.nrows;
842 ncols = X.ncols;
843 nwords = X.nwords;
844 data = X.data;
845}
846
847GF2mat operator*(const GF2mat &X, const GF2mat &Y)
848{
849 it_assert(X.ncols == Y.nrows, "GF2mat::operator*(): dimension mismatch");
850 it_assert(X.nwords > 0, "Gfmat::operator*(): dimension mismatch");
851 it_assert(Y.nwords > 0, "Gfmat::operator*(): dimension mismatch");
852
853 /*
854 // this can be done more efficiently?
855 GF2mat result(X.nrows,Y.ncols);
856 for (int i=0; i<X.nrows; i++) {
857 for (int j=0; j<Y.ncols; j++) {
858 bin b=0;
859 for (int k=0; k<X.ncols; k++) {
860 bin x = X.get(i,k);
861 bin y = Y.get(k,j);
862 b ^= (x&y);
863 }
864 result.set(i,j,b);
865 }
866 }
867 return result; */
868
869 // is this better?
870 return mult_trans(X, Y.transpose());
871}
872
873bvec operator*(const GF2mat &X, const bvec &y)
874{
875 it_assert(length(y) == X.ncols, "GF2mat::operator*(): dimension mismatch");
876 it_assert(X.nwords > 0, "Gfmat::operator*(): dimension mismatch");
877
878 /*
879 // this can be done more efficiently?
880 bvec result = zeros_b(X.nrows);
881 for (int i=0; i<X.nrows; i++) {
882 // do the nwords-1 data columns first
883 for (int j=0; j<X.nwords-1; j++) {
884 int ind = j<<shift_divisor;
885 unsigned char r=X.data(i,j);
886 while (r) {
887 result(i) ^= (r & y(ind));
888 r >>= 1;
889 ind++;
890 }
891 }
892 // do the last column separately
893 for (int j=(X.nwords-1)<<shift_divisor; j<X.ncols; j++) {
894 result(i) ^= (X.get(i,j) & y(j));
895 }
896 }
897 return result; */
898
899 // is this better?
900 return (mult_trans(X, GF2mat(y, 0))).bvecify();
901}
902
903GF2mat mult_trans(const GF2mat &X, const GF2mat &Y)
904{
905 it_assert(X.ncols == Y.ncols, "GF2mat::mult_trans(): dimension mismatch");
906 it_assert(X.nwords > 0, "GF2mat::mult_trans(): dimension mismatch");
907 it_assert(Y.nwords > 0, "GF2mat::mult_trans(): dimension mismatch");
908 it_assert(X.nwords == Y.nwords, "GF2mat::mult_trans(): dimension mismatch");
909
910 GF2mat result(X.nrows, Y.nrows);
911
912 for (int i = 0; i < X.nrows; i++) {
913 for (int j = 0; j < Y.nrows; j++) {
914 bin b = 0;
915 int kindx = i;
916 int kindy = j;
917 for (int k = 0; k < X.nwords; k++) {
918 unsigned char r = X.data(kindx) & Y.data(kindy);
919 /* The following can be speeded up by using a small lookup
920 table for the number of ones and shift only a few times (or
921 not at all if table is large) */
922 while (r) {
923 b ^= r & 1;
924 r >>= 1;
925 };
926 kindx += X.nrows;
927 kindy += Y.nrows;
928 }
929 result.set(i, j, b);
930 }
931 }
932 return result;
933}
934
936{
937 // CAN BE SPEEDED UP
938 GF2mat result(ncols, nrows);
939
940 for (int i = 0; i < nrows; i++) {
941 for (int j = 0; j < ncols; j++) {
942 result.set(j, i, get(i, j));
943 }
944 }
945 return result;
946}
947
948GF2mat operator+(const GF2mat &X, const GF2mat &Y)
949{
950 it_assert(X.nrows == Y.nrows, "GF2mat::operator+(): dimension mismatch");
951 it_assert(X.ncols == Y.ncols, "GF2mat::operator+(): dimension mismatch");
952 it_assert(X.nwords == Y.nwords, "GF2mat::operator+(): dimension mismatch");
953 GF2mat result(X.nrows, X.ncols);
954
955 for (int i = 0; i < X.nrows; i++) {
956 for (int j = 0; j < X.nwords; j++) {
957 result.data(i, j) = X.data(i, j) ^ Y.data(i, j);
958 }
959 }
960
961 return result;
962}
963
964void GF2mat::permute_cols(ivec &perm, bool I)
965{
966 it_assert(length(perm) == ncols,
967 "GF2mat::permute_cols(): dimensions do not match");
968
969 GF2mat temp = (*this);
970 for (int j = 0; j < ncols; j++) {
971 if (I == 0) {
972 set_col(j, temp.get_col(perm(j)));
973 }
974 else {
975 set_col(perm(j), temp.get_col(j));
976 }
977 }
978}
979
980void GF2mat::permute_rows(ivec &perm, bool I)
981{
982 it_assert(length(perm) == nrows,
983 "GF2mat::permute_rows(): dimensions do not match");
984
985 GF2mat temp = (*this);
986 for (int i = 0; i < nrows; i++) {
987 if (I == 0) {
988 for (int j = 0; j < nwords; j++) {
989 data(i, j) = temp.data(perm(i), j);
990 }
991 }
992 else {
993 for (int j = 0; j < nwords; j++) {
994 data(perm(i), j) = temp.data(i, j);
995 }
996 }
997 }
998}
999
1000
1001std::ostream &operator<<(std::ostream &os, const GF2mat &X)
1002{
1003 int i, j;
1004 os << "---- GF(2) matrix of dimension " << X.nrows << "*" << X.ncols
1005 << " -- Density: " << X.density() << " ----" << std::endl;
1006
1007 for (i = 0; i < X.nrows; i++) {
1008 os << " ";
1009 for (j = 0; j < X.ncols; j++) {
1010 os << X.get(i, j) << " ";
1011 }
1012 os << std::endl;
1013 }
1014
1015 return os;
1016}
1017
1018double GF2mat::density() const
1019{
1020 int no_of_ones = 0;
1021
1022 for (int i = 0; i < nrows; i++) {
1023 for (int j = 0; j < ncols; j++) {
1024 no_of_ones += (get(i, j) == 1 ? 1 : 0);
1025 }
1026 }
1027
1028 return ((double) no_of_ones) / (nrows*ncols);
1029}
1030
1031
1033{
1034 // 3 64-bit unsigned words for: nrows, ncols and nwords + rest for char data
1035 uint64_t bytecount = 3 * sizeof(uint64_t)
1036 + X.nrows * X.nwords * sizeof(char);
1037 f.write_data_header("GF2mat", bytecount);
1038
1039 f.low_level_write(static_cast<uint64_t>(X.nrows));
1040 f.low_level_write(static_cast<uint64_t>(X.ncols));
1041 f.low_level_write(static_cast<uint64_t>(X.nwords));
1042 for (int i = 0; i < X.nrows; i++) {
1043 for (int j = 0; j < X.nwords; j++) {
1044 f.low_level_write(static_cast<char>(X.data(i, j)));
1045 }
1046 }
1047 return f;
1048}
1049
1051{
1053
1054 f.read_data_header(h);
1055 if (h.type == "GF2mat") {
1056 uint64_t tmp;
1057 f.low_level_read(tmp);
1058 X.nrows = static_cast<int>(tmp);
1059 f.low_level_read(tmp);
1060 X.ncols = static_cast<int>(tmp);
1061 f.low_level_read(tmp);
1062 X.nwords = static_cast<int>(tmp);
1063 X.data.set_size(X.nrows, X.nwords);
1064 for (int i = 0; i < X.nrows; i++) {
1065 for (int j = 0; j < X.nwords; j++) {
1066 char r;
1067 f.low_level_read(r);
1068 X.data(i, j) = static_cast<unsigned char>(r);
1069 }
1070 }
1071 }
1072 else {
1073 it_error("it_ifile &operator>>() - internal error");
1074 }
1075
1076 return f;
1077}
1078
1079} // namespace itpp
1080
int max_num_m
Maximum weight of rows.
Definition: gf2mat.h:144
int max_num_n
Maximum weight of columns.
Definition: gf2mat.h:146
int M
Size of the matrix: M rows x N columns.
Definition: gf2mat.h:132
imat mlist
List of integer coordinates in the m direction with non-zero entries.
Definition: gf2mat.h:136
void read(const std::string &fname)
Read alist data from a file named fname.
Definition: gf2mat.cpp:46
void write(const std::string &fname) const
Write alist data to a file named fname.
Definition: gf2mat.cpp:156
imat nlist
List of integer coordinates in the n direction with non-zero entries.
Definition: gf2mat.h:138
int N
Size of the matrix: M rows x N columns.
Definition: gf2mat.h:134
ivec num_nlist
Weight of each column n.
Definition: gf2mat.h:142
void from_sparse(const GF2mat_sparse &mat, bool transpose=false)
Import "alist" representation from GF2mat_sparse.
Definition: gf2mat.cpp:217
GF2mat_sparse_alist()
Default constructor.
Definition: gf2mat.h:102
GF2mat_sparse to_sparse(bool transpose=false) const
Convert "alist" representation to GF2mat_sparse.
Definition: gf2mat.cpp:193
ivec num_mlist
Weight of each row m.
Definition: gf2mat.h:140
bool data_ok
Flag indicating that "alist" matrix data are properly set.
Definition: gf2mat.h:130
Class for dense GF(2) matrices.
Definition: gf2mat.h:172
bool is_zero() const
Check whether the matrix is identical to zero.
Definition: gf2mat.cpp:779
int cols() const
Get number of columns.
Definition: gf2mat.h:294
double density() const
Compute the matrix density (fraction of elements equal to "1")
Definition: gf2mat.cpp:1018
int T_fact_update_bitflip(GF2mat &T, GF2mat &U, ivec &P, int rank, int r, int c) const
TXP factorization update, when bit is flipped.
Definition: gf2mat.cpp:614
bool operator==(const GF2mat &X) const
Check if equal.
Definition: gf2mat.cpp:791
GF2mat concatenate_horizontal(const GF2mat &X) const
Concatenate horizontally (append X on the right side of matrix)
Definition: gf2mat.cpp:519
GF2mat transpose() const
Transpose.
Definition: gf2mat.cpp:935
bvec get_row(int i) const
Get row.
Definition: gf2mat.cpp:540
void permute_rows(ivec &perm, bool I)
Multiply from left with permutation matrix (permute rows).
Definition: gf2mat.cpp:980
void addto_element(int i, int j, bin s)
Add s (0 or 1) to element (i,j)
Definition: gf2mat.h:490
void operator=(const GF2mat &X)
Assignment operator.
Definition: gf2mat.cpp:839
void set_col(int j, bvec x)
Set column j to a binary vector x.
Definition: gf2mat.cpp:460
void add_rows(int i, int j)
Add (or equivalently, subtract) rows.
Definition: gf2mat.cpp:809
GF2mat concatenate_vertical(const GF2mat &X) const
Concatenate vertically (append X underneath)
Definition: gf2mat.cpp:496
int rows() const
Get number of rows.
Definition: gf2mat.h:291
bin get(int i, int j) const
Getting element.
Definition: gf2mat.h:498
GF2mat_sparse sparsify() const
Create a sparse GF(2) matrix from a dense GF(2) matrix.
Definition: gf2mat.cpp:417
void swap_cols(int i, int j)
Swap columns i and j.
Definition: gf2mat.cpp:829
bvec bvecify() const
Create a bvec from a GF(2) matrix (must have one column or one row)
Definition: gf2mat.cpp:431
GF2mat get_submatrix(int m1, int n1, int m2, int n2) const
Submatrix from (m1,n1) to (m2,n2)
Definition: gf2mat.cpp:479
ITPP_EXPORT GF2mat gf2dense_eye(int m)
GF(2) Identity matrix.
Definition: gf2mat.cpp:470
int T_fact(GF2mat &T, GF2mat &U, ivec &P) const
TXP factorization.
Definition: gf2mat.cpp:561
void set(int i, int j, bin s)
Set element i,j to s (0 or 1)
Definition: gf2mat.h:505
GF2mat inverse() const
Inversion.
Definition: gf2mat.cpp:748
void set_size(int m, int n, bool copy=false)
Set size of GF(2) matrix. If copy = true, keep data before resizing.
Definition: gf2mat.cpp:406
void set_row(int i, bvec x)
Set row i to a binary vector x.
Definition: gf2mat.cpp:451
GF2mat()
Default constructor (gives an empty 1 x 1 matrix)
Definition: gf2mat.cpp:288
bvec get_col(int j) const
Get column.
Definition: gf2mat.cpp:550
bool T_fact_update_addcol(GF2mat &T, GF2mat &U, ivec &P, bvec newcol) const
TXP factorization update, when column is added.
Definition: gf2mat.cpp:697
void swap_rows(int i, int j)
Swap rows i and j.
Definition: gf2mat.cpp:818
int row_rank() const
Returns the number of linearly independent rows.
Definition: gf2mat.cpp:771
void permute_cols(ivec &perm, bool I)
Multiply a matrix from right with a permutation matrix (i.e., permute the columns).
Definition: gf2mat.cpp:964
void set_size(int rows, int cols, bool copy=false)
Set size of matrix. If copy = true then keep the data before resizing.
Definition: mat.h:647
void clear()
Set matrix equal to the all zero matrix.
Definition: mat.h:245
void compact()
Set the maximum number of non-zero elements in each column equal to the actual number of non-zero ele...
Definition: smat.h:465
void set(int r, int c, T v)
Set element (r, c ) equal to v.
Definition: smat.h:498
void get_col(int c, Sparse_Vec< T > &v) const
Returns column c of the Sparse_Mat in the Sparse_Vec v.
Definition: smat.h:609
int cols() const
Returns the number of columns of the sparse matrix.
Definition: smat.h:158
void set_new(int r, int c, T v)
Set a new element with index (r, c ) equal to v.
Definition: smat.h:505
void transpose(Sparse_Mat< T > &m) const
Definition: smat.h:630
int rows() const
Returns the number of rows of the sparse matrix.
Definition: smat.h:155
Binary arithmetic (boolean) class.
Definition: binary.h:57
The IT++ file format reading and writing class.
Definition: itfile.h:246
void write_data_header(const std::string &type, uint64_t size)
Write the data header for a variable, specifying the type and size of the data to follow.
Definition: itfile.cpp:546
void low_level_write(char x)
Write a char value at the current file pointer position.
Definition: itfile.cpp:716
The IT++ file format reading class.
Definition: itfile.h:133
void low_level_read(char &x)
Read a char value at the current file pointer position.
Definition: itfile.cpp:145
void read_data_header(it_file_base::data_header &h)
Read data header and return the result in the variable h.
Definition: itfile.cpp:134
Definitions of converters between different vector and matrix types.
Definition of a class for algebra on GF(2) (binary) matrices.
#define it_error(s)
Abort unconditionally.
Definition: itassert.h:126
#define it_info_debug(s)
Print information message if NDEBUG is not defined.
Definition: itassert.h:163
#define it_assert_debug(t, s)
Abort if t is not true and NDEBUG is not defined.
Definition: itassert.h:107
#define it_assert(t, s)
Abort if t is not true.
Definition: itassert.h:94
int rank(const Mat< T > &m, double tol=-1.0)
Calculate the rank of matrix m.
Definition: matfunc.h:493
void transpose(const Mat< T > &m, Mat< T > &out)
Transposition of the matrix m returning the transposed matrix in out.
Definition: matfunc.h:308
int length(const Vec< T > &v)
Length of vector.
Definition: matfunc.h:51
T min(const Vec< T > &in)
Minimum value of vector.
Definition: min_max.h:125
T max(const Vec< T > &v)
Maximum value of vector.
Definition: min_max.h:45
ITPP_EXPORT ivec zeros_i(int size)
A Int vector of zeros.
Mat< bin > bmat
bin matrix
Definition: mat.h:508
Various functions on vectors and matrices - header file.
itpp namespace
Definition: itmex.h:37
GF2mat mult_trans(const GF2mat &X, const GF2mat &Y)
Multiplication X*Y' where X and Y are GF(2) matrices.
Definition: gf2mat.cpp:903
std::ostream & operator<<(std::ostream &output, const bin &inbin)
Output stream of bin.
Definition: binary.cpp:36
const Array< T > concat(const Array< T > &a, const T &e)
Append element e to the end of the Array a.
Definition: array.h:486
GF2mat operator*(const GF2mat &X, const GF2mat &Y)
GF(2) matrix multiplication.
Definition: gf2mat.cpp:847
GF2mat gf2dense_eye(int m)
GF(2) Identity matrix.
Definition: gf2mat.cpp:470
std::istream & operator>>(std::istream &input, bin &outbin)
Input stream of bin.
Definition: binary.cpp:42
GF2mat operator+(const GF2mat &X, const GF2mat &Y)
GF(2) matrix addition.
Definition: gf2mat.cpp:948
int floor_i(double x)
The nearest smaller integer.
Definition: converters.h:350
Definitions of special vectors and matrices.
Data header structure.
Definition: itfile.h:98
std::string type
Data type, e.g. int32, float32, etc. type = "" means deleted.
Definition: itfile.h:108
SourceForge Logo

Generated on Sun Jun 5 2022 21:26:42 for IT++ by Doxygen 1.9.3