Graphviz 14.0.3~dev.20251104.0241
Loading...
Searching...
No Matches
SparseMatrix.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#include <stdio.h>
12#include <string.h>
13#include <math.h>
14#include <assert.h>
15#include <common/arith.h>
16#include <limits.h>
17#include <sparse/SparseMatrix.h>
18#include <stddef.h>
19#include <stdbool.h>
20#include <util/alloc.h>
21
22static size_t size_of_matrix_type(int type){
23 size_t size = 0;
24 switch (type){
26 size = sizeof(double);
27 break;
29 size = 2*sizeof(double);
30 break;
32 size = sizeof(int);
33 break;
35 size = 0;
36 break;
38 size = 0;
39 break;
40 default:
41 size = 0;
42 break;
43 }
44
45 return size;
46}
47
57 /* make it strictly low diag only, and set flag to undirected */
59 B = SparseMatrix_symmetrize(A, false);
60 B->is_undirected = true;
62}
64 if (!A) return NULL;
65
66 int *ia = A->ia, *ja = A->ja, *ib, *jb, nz = A->nz, m = A->m, n = A->n, type = A->type, format = A->format;
68 int i, j;
69
70 assert(A->format == FORMAT_CSR);/* only implemented for CSR right now */
71
72 B = SparseMatrix_new(n, m, nz, type, format);
73 B->nz = nz;
74 ib = B->ia;
75 jb = B->ja;
76
77 for (i = 0; i <= n; i++) ib[i] = 0;
78 for (i = 0; i < m; i++){
79 for (j = ia[i]; j < ia[i+1]; j++){
80 ib[ja[j]+1]++;
81 }
82 }
83
84 for (i = 0; i < n; i++) ib[i+1] += ib[i];
85
86 switch (A->type){
87 case MATRIX_TYPE_REAL:{
88 double *a = A->a;
89 double *b = B->a;
90 for (i = 0; i < m; i++){
91 for (j = ia[i]; j < ia[i+1]; j++){
92 jb[ib[ja[j]]] = i;
93 b[ib[ja[j]]++] = a[j];
94 }
95 }
96 break;
97 }
99 double *a = A->a;
100 double *b = B->a;
101 for (i = 0; i < m; i++){
102 for (j = ia[i]; j < ia[i+1]; j++){
103 jb[ib[ja[j]]] = i;
104 b[2*ib[ja[j]]] = a[2*j];
105 b[2*ib[ja[j]]+1] = a[2*j+1];
106 ib[ja[j]]++;
107 }
108 }
109 break;
110 }
112 int *ai = A->a;
113 int *bi = B->a;
114 for (i = 0; i < m; i++){
115 for (j = ia[i]; j < ia[i+1]; j++){
116 jb[ib[ja[j]]] = i;
117 bi[ib[ja[j]]++] = ai[j];
118 }
119 }
120 break;
121 }
123 for (i = 0; i < m; i++){
124 for (j = ia[i]; j < ia[i+1]; j++){
125 jb[ib[ja[j]]++] = i;
126 }
127 }
128 break;
131 return NULL;
132 default:
134 return NULL;
135 }
136
137
138 for (i = n-1; i >= 0; i--) ib[i+1] = ib[i];
139 ib[0] = 0;
140
141
142 return B;
143}
144
146 bool pattern_symmetric_only) {
148 if (SparseMatrix_is_symmetric(A, pattern_symmetric_only)) return SparseMatrix_copy(A);
150 if (!B) return NULL;
151 A = SparseMatrix_add(A, B);
153 A->is_symmetric = true;
154 A->is_pattern_symmetric = true;
155 return A;
156}
157
158bool SparseMatrix_is_symmetric(SparseMatrix A, bool test_pattern_symmetry_only) {
159 if (!A) return false;
160
161 /* assume no repeated entries! */
163 int *ia, *ja, *ib, *jb, type, m;
164 int *mask;
165 bool res = false;
166 int i, j;
167 assert(A->format == FORMAT_CSR);/* only implemented for CSR right now */
168
169 if (A->is_symmetric) return true;
170 if (test_pattern_symmetry_only && A->is_pattern_symmetric) return true;
171
172 if (A->m != A->n) return false;
173
175 if (!B) return false;
176
177 ia = A->ia;
178 ja = A->ja;
179 ib = B->ia;
180 jb = B->ja;
181 m = A->m;
182
183 mask = gv_calloc((size_t)m, sizeof(int));
184 for (i = 0; i < m; i++) mask[i] = -1;
185
186 type = A->type;
187 if (test_pattern_symmetry_only) type = MATRIX_TYPE_PATTERN;
188
189 switch (type){
190 case MATRIX_TYPE_REAL:{
191 double *a = A->a;
192 double *b = B->a;
193 for (i = 0; i <= m; i++) if (ia[i] != ib[i]) goto RETURN;
194 for (i = 0; i < m; i++){
195 for (j = ia[i]; j < ia[i+1]; j++){
196 mask[ja[j]] = j;
197 }
198 for (j = ib[i]; j < ib[i+1]; j++){
199 if (mask[jb[j]] < ia[i]) goto RETURN;
200 }
201 for (j = ib[i]; j < ib[i+1]; j++){
202 if (fabs(b[j] - a[mask[jb[j]]]) > SYMMETRY_EPSILON) goto RETURN;
203 }
204 }
205 res = true;
206 break;
207 }
209 double *a = A->a;
210 double *b = B->a;
211 for (i = 0; i <= m; i++) if (ia[i] != ib[i]) goto RETURN;
212 for (i = 0; i < m; i++){
213 for (j = ia[i]; j < ia[i+1]; j++){
214 mask[ja[j]] = j;
215 }
216 for (j = ib[i]; j < ib[i+1]; j++){
217 if (mask[jb[j]] < ia[i]) goto RETURN;
218 }
219 for (j = ib[i]; j < ib[i+1]; j++){
220 if (fabs(b[2*j] - a[2*mask[jb[j]]]) > SYMMETRY_EPSILON) goto RETURN;
221 if (fabs(b[2*j+1] - a[2*mask[jb[j]]+1]) > SYMMETRY_EPSILON) goto RETURN;
222 }
223 }
224 res = true;
225 break;
226 }
228 int *ai = A->a;
229 int *bi = B->a;
230 for (i = 0; i < m; i++){
231 for (j = ia[i]; j < ia[i+1]; j++){
232 mask[ja[j]] = j;
233 }
234 for (j = ib[i]; j < ib[i+1]; j++){
235 if (mask[jb[j]] < ia[i]) goto RETURN;
236 }
237 for (j = ib[i]; j < ib[i+1]; j++){
238 if (bi[j] != ai[mask[jb[j]]]) goto RETURN;
239 }
240 }
241 res = true;
242 break;
243 }
245 for (i = 0; i < m; i++){
246 for (j = ia[i]; j < ia[i+1]; j++){
247 mask[ja[j]] = j;
248 }
249 for (j = ib[i]; j < ib[i+1]; j++){
250 if (mask[jb[j]] < ia[i]) goto RETURN;
251 }
252 }
253 res = true;
254 break;
256 goto RETURN;
257 break;
258 default:
259 goto RETURN;
260 break;
261 }
262
263 if (!test_pattern_symmetry_only) {
264 A->is_symmetric = true;
265 }
266 A->is_pattern_symmetric = true;
267 RETURN:
268 free(mask);
269
271 return res;
272}
273
274static SparseMatrix SparseMatrix_init(int m, int n, int type, size_t sz, int format){
275 SparseMatrix A = gv_alloc(sizeof(struct SparseMatrix_struct));
276 A->m = m;
277 A->n = n;
278 A->nz = 0;
279 A->nzmax = 0;
280 A->type = type;
281 A->size = sz;
282 switch (format){
283 case FORMAT_COORD:
284 A->ia = NULL;
285 break;
286 case FORMAT_CSR:
287 default:
288 A->ia = gv_calloc((size_t)(m + 1), sizeof(int));
289 }
290 A->ja = NULL;
291 A->a = NULL;
292 A->format = format;
293 return A;
294}
295
297 int format = A->format;
298 size_t nz_t = (size_t) nz; /* size_t is 64 bit on 64 bit machine. Using nz*A->size can overflow. */
299
300 A->a = NULL;
301 switch (format){
302 case FORMAT_COORD:
303 A->ia = gv_calloc(nz_t, sizeof(int));
304 A->ja = gv_calloc(nz_t, sizeof(int));
305 A->a = gv_calloc(nz_t, A->size);
306 break;
307 case FORMAT_CSR:
308 default:
309 A->ja = gv_calloc(nz_t, sizeof(int));
310 if (A->size > 0 && nz_t > 0) {
311 A->a = gv_calloc(nz_t, A->size);
312 }
313 break;
314 }
315 A->nzmax = nz;
316 return A;
317}
318
320 int format = A->format;
321 size_t nz_t = (size_t) nz; /* size_t is 64 bit on 64 bit machine. Using nz*A->size can overflow. */
322
323 switch (format){
324 case FORMAT_COORD:
325 A->ia = gv_recalloc(A->ia, A->nzmax, nz_t, sizeof(int));
326 A->ja = gv_recalloc(A->ja, A->nzmax, nz_t, sizeof(int));
327 if (A->size > 0) {
328 if (A->a){
329 A->a = gv_recalloc(A->a, A->nzmax, nz_t, A->size);
330 } else {
331 A->a = gv_calloc(nz_t, A->size);
332 }
333 }
334 break;
335 case FORMAT_CSR:
336 default:
337 A->ja = gv_recalloc(A->ja, A->nzmax, nz_t, sizeof(int));
338 if (A->size > 0) {
339 if (A->a){
340 A->a = gv_recalloc(A->a, A->nzmax, nz_t, A->size);
341 } else {
342 A->a = gv_calloc(nz_t, A->size);
343 }
344 }
345 break;
346 }
347 A->nzmax = nz;
348 return A;
349}
350
351SparseMatrix SparseMatrix_new(int m, int n, int nz, int type, int format){
352 /* return a sparse matrix skeleton with row dimension m and storage nz. If nz == 0,
353 only row pointers are allocated */
355 size_t sz;
356
358 A = SparseMatrix_init(m, n, type, sz, format);
359
360 if (nz > 0) A = SparseMatrix_alloc(A, nz);
361 return A;
362
363}
364SparseMatrix SparseMatrix_general_new(int m, int n, int nz, int type, size_t sz, int format){
365 /* return a sparse matrix skeleton with row dimension m and storage nz. If nz == 0,
366 only row pointers are allocated. this is more general and allow elements to be
367 any data structure, not just real/int/complex etc
368 */
370
371 A = SparseMatrix_init(m, n, type, sz, format);
372
373 if (nz > 0) A = SparseMatrix_alloc(A, nz);
374 return A;
375
376}
377
379 if (!A) return;
380 free(A->ia);
381 free(A->ja);
382 free(A->a);
383 free(A);
384}
385
387 const int m = A->m;
388
389 switch (A->type){
390 case MATRIX_TYPE_REAL:
391 fprintf(f,"%%%%MatrixMarket matrix coordinate real general\n");
392 break;
394 fprintf(f,"%%%%MatrixMarket matrix coordinate complex general\n");
395 break;
397 fprintf(f,"%%%%MatrixMarket matrix coordinate integer general\n");
398 break;
400 fprintf(f,"%%%%MatrixMarket matrix coordinate pattern general\n");
401 break;
403 return;
404 default:
405 return;
406 }
407
408 fprintf(f,"%d %d %d\n",A->m,A->n,A->nz);
409 const int *const ia = A->ia;
410 const int *const ja = A->ja;
411 switch (A->type){
412 case MATRIX_TYPE_REAL: {
413 const double *const a = A->a;
414 for (int i = 0; i < m; i++){
415 for (int j = ia[i]; j < ia[i+1]; j++){
416 fprintf(f, "%d %d %16.8g\n",i+1, ja[j]+1, a[j]);
417 }
418 }
419 break;
420 }
421 case MATRIX_TYPE_COMPLEX: {
422 const double *const a = A->a;
423 for (int i = 0; i < m; i++){
424 for (int j = ia[i]; j < ia[i+1]; j++){
425 fprintf(f, "%d %d %16.8g %16.8g\n",i+1, ja[j]+1, a[2*j], a[2*j+1]);
426 }
427 }
428 break;
429 }
430 case MATRIX_TYPE_INTEGER: {
431 const int *const ai = A->a;
432 for (int i = 0; i < m; i++){
433 for (int j = ia[i]; j < ia[i+1]; j++){
434 fprintf(f, "%d %d %d\n",i+1, ja[j]+1, ai[j]);
435 }
436 }
437 break;
438 }
440 for (int i = 0; i < m; i++){
441 for (int j = ia[i]; j < ia[i+1]; j++){
442 fprintf(f, "%d %d\n",i+1, ja[j]+1);
443 }
444 }
445 break;
447 return;
448 default:
449 return;
450 }
451
452}
453
455 int *ia, *ja;
456 double *a;
457 int *ai;
458 int i;
459
460 switch (A->type){
461 case MATRIX_TYPE_REAL:
462 fprintf(f,"%%%%MatrixMarket matrix coordinate real general\n");
463 break;
465 fprintf(f,"%%%%MatrixMarket matrix coordinate complex general\n");
466 break;
468 fprintf(f,"%%%%MatrixMarket matrix coordinate integer general\n");
469 break;
471 fprintf(f,"%%%%MatrixMarket matrix coordinate pattern general\n");
472 break;
474 return;
475 default:
476 return;
477 }
478
479 fprintf(f,"%d %d %d\n",A->m,A->n,A->nz);
480 ia = A->ia;
481 ja = A->ja;
482 a = A->a;
483 switch (A->type){
484 case MATRIX_TYPE_REAL:
485 a = A->a;
486 for (i = 0; i < A->nz; i++){
487 fprintf(f, "%d %d %16.8g\n",ia[i]+1, ja[i]+1, a[i]);
488 }
489 break;
491 a = A->a;
492 for (i = 0; i < A->nz; i++){
493 fprintf(f, "%d %d %16.8g %16.8g\n",ia[i]+1, ja[i]+1, a[2*i], a[2*i+1]);
494 }
495 break;
497 ai = A->a;
498 for (i = 0; i < A->nz; i++){
499 fprintf(f, "%d %d %d\n",ia[i]+1, ja[i]+1, ai[i]);
500 }
501 break;
503 for (i = 0; i < A->nz; i++){
504 fprintf(f, "%d %d\n",ia[i]+1, ja[i]+1);
505 }
506 break;
508 return;
509 default:
510 return;
511 }
512}
513
514
515
517
518 switch (A->format){
519 case FORMAT_CSR:
521 break;
522 case FORMAT_COORD:
524 break;
525 default:
526 assert(0);
527 }
528}
529
530
532 /* convert a sparse matrix in coordinate form to one in compressed row form.*/
533 int *irn, *jcn;
534
535 void *a = A->a;
536
537 assert(A->format == FORMAT_COORD);
538 if (A->format != FORMAT_COORD) {
539 return NULL;
540 }
541 irn = A->ia;
542 jcn = A->ja;
543 return SparseMatrix_from_coordinate_arrays(A->nz, A->m, A->n, irn, jcn, a, A->type, A->size);
544
545}
547 /* convert a sparse matrix in coordinate form to one in compressed row form.*/
548 int *irn, *jcn;
549
550 void *a = A->a;
551
552 assert(A->format == FORMAT_COORD);
553 if (A->format != FORMAT_COORD) {
554 return NULL;
555 }
556 irn = A->ia;
557 jcn = A->ja;
558 return SparseMatrix_from_coordinate_arrays_not_compacted(A->nz, A->m, A->n, irn, jcn, a, A->type, A->size);
559}
560
562 int n,
563 int *irn,
564 int *jcn,
565 const void *val0,
566 int type,
567 size_t sz,
568 int sum_repeated) {
569 /* convert a sparse matrix in coordinate form to one in compressed row form.
570 nz: number of entries
571 irn: row indices 0-based
572 jcn: column indices 0-based
573 val values if not NULL
574 type: matrix type
575 */
576
578 int *ia, *ja;
579 double *a;
580 int *ai;
581 int i;
582
583 assert(m > 0 && n > 0 && nz >= 0);
584
585 if (m <=0 || n <= 0 || nz < 0) return NULL;
586 A = SparseMatrix_general_new(m, n, nz, type, sz, FORMAT_CSR);
587 assert(A);
588 if (!A) return NULL;
589 ia = A->ia;
590 ja = A->ja;
591
592 for (i = 0; i <= m; i++){
593 ia[i] = 0;
594 }
595
596 switch (type){
597 case MATRIX_TYPE_REAL: {
598 const double *const val = val0;
599 a = A->a;
600 for (i = 0; i < nz; i++){
601 if (irn[i] < 0 || irn[i] >= m || jcn[i] < 0 || jcn[i] >= n) {
602 assert(0);
603 return NULL;
604 }
605 ia[irn[i]+1]++;
606 }
607 for (i = 0; i < m; i++) ia[i+1] += ia[i];
608 for (i = 0; i < nz; i++){
609 a[ia[irn[i]]] = val[i];
610 ja[ia[irn[i]]++] = jcn[i];
611 }
612 for (i = m; i > 0; i--) ia[i] = ia[i - 1];
613 ia[0] = 0;
614 break;
615 }
616 case MATRIX_TYPE_COMPLEX: {
617 const double *const val = val0;
618 a = A->a;
619 for (i = 0; i < nz; i++){
620 if (irn[i] < 0 || irn[i] >= m || jcn[i] < 0 || jcn[i] >= n) {
621 assert(0);
622 return NULL;
623 }
624 ia[irn[i]+1]++;
625 }
626 for (i = 0; i < m; i++) ia[i+1] += ia[i];
627 for (i = 0; i < nz; i++){
628 a[2*ia[irn[i]]] = val[2 * i];
629 a[2*ia[irn[i]]+1] = val[2 * i + 1];
630 ja[ia[irn[i]]++] = jcn[i];
631 }
632 for (i = m; i > 0; i--) ia[i] = ia[i - 1];
633 ia[0] = 0;
634 break;
635 }
636 case MATRIX_TYPE_INTEGER: {
637 const int *const vali = val0;
638 ai = A->a;
639 for (i = 0; i < nz; i++){
640 if (irn[i] < 0 || irn[i] >= m || jcn[i] < 0 || jcn[i] >= n) {
641 assert(0);
642 return NULL;
643 }
644 ia[irn[i]+1]++;
645 }
646 for (i = 0; i < m; i++) ia[i+1] += ia[i];
647 for (i = 0; i < nz; i++){
648 ai[ia[irn[i]]] = vali[i];
649 ja[ia[irn[i]]++] = jcn[i];
650 }
651 for (i = m; i > 0; i--) ia[i] = ia[i - 1];
652 ia[0] = 0;
653 break;
654 }
656 for (i = 0; i < nz; i++){
657 if (irn[i] < 0 || irn[i] >= m || jcn[i] < 0 || jcn[i] >= n) {
658 assert(0);
659 return NULL;
660 }
661 ia[irn[i]+1]++;
662 }
663 for (i = 0; i < m; i++) ia[i+1] += ia[i];
664 for (i = 0; i < nz; i++){
665 ja[ia[irn[i]]++] = jcn[i];
666 }
667 for (i = m; i > 0; i--) ia[i] = ia[i - 1];
668 ia[0] = 0;
669 break;
671 for (i = 0; i < nz; i++){
672 if (irn[i] < 0 || irn[i] >= m || jcn[i] < 0 || jcn[i] >= n) {
673 assert(0);
674 return NULL;
675 }
676 ia[irn[i]+1]++;
677 }
678 for (i = 0; i < m; i++) ia[i+1] += ia[i];
679 memcpy(A->a, val0, A->size*((size_t)nz));
680 for (i = 0; i < nz; i++){
681 ja[ia[irn[i]]++] = jcn[i];
682 }
683 for (i = m; i > 0; i--) ia[i] = ia[i - 1];
684 ia[0] = 0;
685 break;
686 default:
687 assert(0);
688 return NULL;
689 }
690 A->nz = nz;
691
692
693
694 if(sum_repeated) A = SparseMatrix_sum_repeat_entries(A);
695
696 return A;
697}
698
700 int *jcn, const void *val,
701 int type, size_t sz) {
702 return SparseMatrix_from_coordinate_arrays_internal(nz, m, n, irn, jcn, val, type, sz, SUM_REPEATED_ALL);
703}
704
705
706SparseMatrix SparseMatrix_from_coordinate_arrays_not_compacted(int nz, int m, int n, int *irn, int *jcn, void *val0, int type, size_t sz){
707 return SparseMatrix_from_coordinate_arrays_internal(nz, m, n, irn, jcn, val0, type, sz, SUM_REPEATED_NONE);
708}
709
711 int m, n;
713 int *mask = NULL;
714 int *ia = A->ia, *ja = A->ja, *ib = B->ia, *jb = B->ja, *ic, *jc;
715 int i, j, nz, nzmax;
716
717 assert(A && B);
718 assert(A->format == B->format && A->format == FORMAT_CSR);/* other format not yet supported */
719 assert(A->type == B->type);
720 m = A->m;
721 n = A->n;
722 if (m != B->m || n != B->n) return NULL;
723
724 nzmax = A->nz + B->nz;/* just assume that no entries overlaps for speed */
725
726 C = SparseMatrix_new(m, n, nzmax, A->type, FORMAT_CSR);
727 if (!C) goto RETURN;
728 ic = C->ia;
729 jc = C->ja;
730
731 mask = gv_calloc((size_t)n, sizeof(int));
732
733 for (i = 0; i < n; i++) mask[i] = -1;
734
735 nz = 0;
736 ic[0] = 0;
737 switch (A->type){
738 case MATRIX_TYPE_REAL:{
739 double *a = A->a;
740 double *b = B->a;
741 double *c = C->a;
742 for (i = 0; i < m; i++){
743 for (j = ia[i]; j < ia[i+1]; j++){
744 mask[ja[j]] = nz;
745 jc[nz] = ja[j];
746 c[nz] = a[j];
747 nz++;
748 }
749 for (j = ib[i]; j < ib[i+1]; j++){
750 if (mask[jb[j]] < ic[i]){
751 jc[nz] = jb[j];
752 c[nz++] = b[j];
753 } else {
754 c[mask[jb[j]]] += b[j];
755 }
756 }
757 ic[i+1] = nz;
758 }
759 break;
760 }
762 double *a = A->a;
763 double *b = B->a;
764 double *c = C->a;
765 for (i = 0; i < m; i++){
766 for (j = ia[i]; j < ia[i+1]; j++){
767 mask[ja[j]] = nz;
768 jc[nz] = ja[j];
769 c[2*nz] = a[2*j];
770 c[2*nz+1] = a[2*j+1];
771 nz++;
772 }
773 for (j = ib[i]; j < ib[i+1]; j++){
774 if (mask[jb[j]] < ic[i]){
775 jc[nz] = jb[j];
776 c[2*nz] = b[2*j];
777 c[2*nz+1] = b[2*j+1];
778 nz++;
779 } else {
780 c[2*mask[jb[j]]] += b[2*j];
781 c[2*mask[jb[j]]+1] += b[2*j+1];
782 }
783 }
784 ic[i+1] = nz;
785 }
786 break;
787 }
789 int *a = A->a;
790 int *b = B->a;
791 int *c = C->a;
792 for (i = 0; i < m; i++){
793 for (j = ia[i]; j < ia[i+1]; j++){
794 mask[ja[j]] = nz;
795 jc[nz] = ja[j];
796 c[nz] = a[j];
797 nz++;
798 }
799 for (j = ib[i]; j < ib[i+1]; j++){
800 if (mask[jb[j]] < ic[i]){
801 jc[nz] = jb[j];
802 c[nz] = b[j];
803 nz++;
804 } else {
805 c[mask[jb[j]]] += b[j];
806 }
807 }
808 ic[i+1] = nz;
809 }
810 break;
811 }
813 for (i = 0; i < m; i++){
814 for (j = ia[i]; j < ia[i+1]; j++){
815 mask[ja[j]] = nz;
816 jc[nz] = ja[j];
817 nz++;
818 }
819 for (j = ib[i]; j < ib[i+1]; j++){
820 if (mask[jb[j]] < ic[i]){
821 jc[nz] = jb[j];
822 nz++;
823 }
824 }
825 ic[i+1] = nz;
826 }
827 break;
828 }
830 break;
831 default:
832 break;
833 }
834 C->nz = nz;
835
836 RETURN:
837 free(mask);
838
839 return C;
840}
841
842void SparseMatrix_multiply_dense(SparseMatrix A, const double *v, double *res,
843 int dim) {
844 // A × V, with A dimension m × n, with V a dense matrix of dimension n × dim.
845 // v[i×dim×j] gives V[i,j]. Result of dimension m × dim. Real only for now.
846 int i, j, k, *ia, *ja, m;
847 double *a;
848
849 assert(A->format == FORMAT_CSR);
850 assert(A->type == MATRIX_TYPE_REAL);
851
852 a = A->a;
853 ia = A->ia;
854 ja = A->ja;
855 m = A->m;
856
857 for (i = 0; i < m; i++){
858 for (k = 0; k < dim; k++) res[i * dim + k] = 0;
859 for (j = ia[i]; j < ia[i+1]; j++){
860 for (k = 0; k < dim; k++) res[i * dim + k] += a[j] * v[ja[j] *dim + k];
861 }
862 }
863}
864
865void SparseMatrix_multiply_vector(SparseMatrix A, double *v, double **res) {
866 /* A v or A^T v. Real only for now. */
867 int i, j, *ia, *ja, m;
868 double *a, *u = NULL;
869 int *ai;
870 assert(A->format == FORMAT_CSR);
871 assert(A->type == MATRIX_TYPE_REAL || A->type == MATRIX_TYPE_INTEGER);
872
873 ia = A->ia;
874 ja = A->ja;
875 m = A->m;
876 u = *res;
877
878 switch (A->type){
879 case MATRIX_TYPE_REAL:
880 a = A->a;
881 if (v){
882 if (!u) u = gv_calloc((size_t)m, sizeof(double));
883 for (i = 0; i < m; i++){
884 u[i] = 0.;
885 for (j = ia[i]; j < ia[i+1]; j++){
886 u[i] += a[j]*v[ja[j]];
887 }
888 }
889 } else {
890 /* v is assumed to be all 1's */
891 if (!u) u = gv_calloc((size_t)m, sizeof(double));
892 for (i = 0; i < m; i++){
893 u[i] = 0.;
894 for (j = ia[i]; j < ia[i+1]; j++){
895 u[i] += a[j];
896 }
897 }
898 }
899 break;
901 ai = A->a;
902 if (v){
903 if (!u) u = gv_calloc((size_t)m, sizeof(double));
904 for (i = 0; i < m; i++){
905 u[i] = 0.;
906 for (j = ia[i]; j < ia[i+1]; j++){
907 u[i] += ai[j]*v[ja[j]];
908 }
909 }
910 } else {
911 /* v is assumed to be all 1's */
912 if (!u) u = gv_calloc((size_t)m, sizeof(double));
913 for (i = 0; i < m; i++){
914 u[i] = 0.;
915 for (j = ia[i]; j < ia[i+1]; j++){
916 u[i] += ai[j];
917 }
918 }
919 }
920 break;
921 default:
922 assert(0);
923 u = NULL;
924 }
925 *res = u;
926
927}
928
930 int m;
932 int *mask = NULL;
933 int *ia = A->ia, *ja = A->ja, *ib = B->ia, *jb = B->ja, *ic, *jc;
934 int i, j, k, jj, type, nz;
935
936 assert(A->format == B->format && A->format == FORMAT_CSR);/* other format not yet supported */
937
938 m = A->m;
939 if (A->n != B->m) return NULL;
940 if (A->type != B->type){
941#ifdef DEBUG
942 printf("in SparseMatrix_multiply, the matrix types do not match, right now only multiplication of matrices of the same type is supported\n");
943#endif
944 return NULL;
945 }
946 type = A->type;
947
948 mask = calloc((size_t)B->n, sizeof(int));
949 if (!mask) return NULL;
950
951 for (i = 0; i < B->n; i++) mask[i] = -1;
952
953 nz = 0;
954 for (i = 0; i < m; i++){
955 for (j = ia[i]; j < ia[i+1]; j++){
956 jj = ja[j];
957 for (k = ib[jj]; k < ib[jj+1]; k++){
958 if (mask[jb[k]] != -i - 2){
959 if ((nz+1) <= nz) {
960#ifdef DEBUG_PRINT
961 fprintf(stderr,"overflow in SparseMatrix_multiply !!!\n");
962#endif
963 free(mask);
964 return NULL;
965 }
966 nz++;
967 mask[jb[k]] = -i - 2;
968 }
969 }
970 }
971 }
972
973 C = SparseMatrix_new(m, B->n, nz, type, FORMAT_CSR);
974 if (!C) goto RETURN;
975 ic = C->ia;
976 jc = C->ja;
977
978 nz = 0;
979
980 switch (type){
981 case MATRIX_TYPE_REAL:
982 {
983 double *a = A->a;
984 double *b = B->a;
985 double *c = C->a;
986 ic[0] = 0;
987 for (i = 0; i < m; i++){
988 for (j = ia[i]; j < ia[i+1]; j++){
989 jj = ja[j];
990 for (k = ib[jj]; k < ib[jj+1]; k++){
991 if (mask[jb[k]] < ic[i]){
992 mask[jb[k]] = nz;
993 jc[nz] = jb[k];
994 c[nz] = a[j]*b[k];
995 nz++;
996 } else {
997 assert(jc[mask[jb[k]]] == jb[k]);
998 c[mask[jb[k]]] += a[j]*b[k];
999 }
1000 }
1001 }
1002 ic[i+1] = nz;
1003 }
1004 }
1005 break;
1007 {
1008 double *a = A->a;
1009 double *b = B->a;
1010 double *c = C->a;
1011 ic[0] = 0;
1012 for (i = 0; i < m; i++){
1013 for (j = ia[i]; j < ia[i+1]; j++){
1014 jj = ja[j];
1015 for (k = ib[jj]; k < ib[jj+1]; k++){
1016 if (mask[jb[k]] < ic[i]){
1017 mask[jb[k]] = nz;
1018 jc[nz] = jb[k];
1019 c[2*nz] = a[2*j]*b[2*k] - a[2*j+1]*b[2*k+1];/*real part */
1020 c[2*nz+1] = a[2*j]*b[2*k+1] + a[2*j+1]*b[2*k];/*img part */
1021 nz++;
1022 } else {
1023 assert(jc[mask[jb[k]]] == jb[k]);
1024 c[2*mask[jb[k]]] += a[2*j]*b[2*k] - a[2*j+1]*b[2*k+1];/*real part */
1025 c[2*mask[jb[k]]+1] += a[2*j]*b[2*k+1] + a[2*j+1]*b[2*k];/*img part */
1026 }
1027 }
1028 }
1029 ic[i+1] = nz;
1030 }
1031 }
1032 break;
1034 {
1035 int *a = A->a;
1036 int *b = B->a;
1037 int *c = C->a;
1038 ic[0] = 0;
1039 for (i = 0; i < m; i++){
1040 for (j = ia[i]; j < ia[i+1]; j++){
1041 jj = ja[j];
1042 for (k = ib[jj]; k < ib[jj+1]; k++){
1043 if (mask[jb[k]] < ic[i]){
1044 mask[jb[k]] = nz;
1045 jc[nz] = jb[k];
1046 c[nz] = a[j]*b[k];
1047 nz++;
1048 } else {
1049 assert(jc[mask[jb[k]]] == jb[k]);
1050 c[mask[jb[k]]] += a[j]*b[k];
1051 }
1052 }
1053 }
1054 ic[i+1] = nz;
1055 }
1056 }
1057 break;
1059 ic[0] = 0;
1060 for (i = 0; i < m; i++){
1061 for (j = ia[i]; j < ia[i+1]; j++){
1062 jj = ja[j];
1063 for (k = ib[jj]; k < ib[jj+1]; k++){
1064 if (mask[jb[k]] < ic[i]){
1065 mask[jb[k]] = nz;
1066 jc[nz] = jb[k];
1067 nz++;
1068 } else {
1069 assert(jc[mask[jb[k]]] == jb[k]);
1070 }
1071 }
1072 }
1073 ic[i+1] = nz;
1074 }
1075 break;
1077 default:
1079 C = NULL; goto RETURN;
1080 break;
1081 }
1082
1083 C->nz = nz;
1084
1085 RETURN:
1086 free(mask);
1087 return C;
1088}
1089
1090
1091
1093 int m;
1095 int *mask = NULL;
1096 int *ia = A->ia, *ja = A->ja, *ib = B->ia, *jb = B->ja, *ic = C->ia, *jc = C->ja, *id, *jd;
1097 int i, j, k, l, ll, jj, type, nz;
1098
1099 assert(A->format == B->format && A->format == FORMAT_CSR);/* other format not yet supported */
1100
1101 m = A->m;
1102 if (A->n != B->m) return NULL;
1103 if (B->n != C->m) return NULL;
1104
1105 if (A->type != B->type || B->type != C->type){
1106#ifdef DEBUG
1107 printf("in SparseMatrix_multiply, the matrix types do not match, right now only multiplication of matrices of the same type is supported\n");
1108#endif
1109 return NULL;
1110 }
1111 type = A->type;
1112
1113 assert(type == MATRIX_TYPE_REAL);
1114
1115 mask = calloc((size_t)C->n, sizeof(int));
1116 if (!mask) return NULL;
1117
1118 for (i = 0; i < C->n; i++) mask[i] = -1;
1119
1120 nz = 0;
1121 for (i = 0; i < m; i++){
1122 for (j = ia[i]; j < ia[i+1]; j++){
1123 jj = ja[j];
1124 for (l = ib[jj]; l < ib[jj+1]; l++){
1125 ll = jb[l];
1126 for (k = ic[ll]; k < ic[ll+1]; k++){
1127 if (mask[jc[k]] != -i - 2){
1128 if ((nz+1) <= nz) {
1129#ifdef DEBUG_PRINT
1130 fprintf(stderr,"overflow in SparseMatrix_multiply !!!\n");
1131#endif
1132 return NULL;
1133 }
1134 nz++;
1135 mask[jc[k]] = -i - 2;
1136 }
1137 }
1138 }
1139 }
1140 }
1141
1142 D = SparseMatrix_new(m, C->n, nz, type, FORMAT_CSR);
1143 if (!D) goto RETURN;
1144 id = D->ia;
1145 jd = D->ja;
1146
1147 nz = 0;
1148
1149 double *a = A->a;
1150 double *b = B->a;
1151 double *c = C->a;
1152 double *d = D->a;
1153 id[0] = 0;
1154 for (i = 0; i < m; i++){
1155 for (j = ia[i]; j < ia[i+1]; j++){
1156 jj = ja[j];
1157 for (l = ib[jj]; l < ib[jj+1]; l++){
1158 ll = jb[l];
1159 for (k = ic[ll]; k < ic[ll+1]; k++){
1160 if (mask[jc[k]] < id[i]){
1161 mask[jc[k]] = nz;
1162 jd[nz] = jc[k];
1163 d[nz] = a[j]*b[l]*c[k];
1164 nz++;
1165 } else {
1166 assert(jd[mask[jc[k]]] == jc[k]);
1167 d[mask[jc[k]]] += a[j]*b[l]*c[k];
1168 }
1169 }
1170 }
1171 }
1172 id[i+1] = nz;
1173 }
1174
1175 D->nz = nz;
1176
1177 RETURN:
1178 free(mask);
1179 return D;
1180}
1181
1183 /* sum repeated entries in the same row, i.e., {1,1}->1, {1,1}->2 becomes {1,1}->3 */
1184 int *ia = A->ia, *ja = A->ja, type = A->type, n = A->n;
1185 int *mask = NULL, nz = 0, i, j, sta;
1186
1187 mask = gv_calloc((size_t)n, sizeof(int));
1188 for (i = 0; i < n; i++) mask[i] = -1;
1189
1190 switch (type){
1191 case MATRIX_TYPE_REAL:
1192 {
1193 double *a = A->a;
1194 nz = 0;
1195 sta = ia[0];
1196 for (i = 0; i < A->m; i++){
1197 for (j = sta; j < ia[i+1]; j++){
1198 if (mask[ja[j]] < ia[i]){
1199 ja[nz] = ja[j];
1200 a[nz] = a[j];
1201 mask[ja[j]] = nz++;
1202 } else {
1203 assert(ja[mask[ja[j]]] == ja[j]);
1204 a[mask[ja[j]]] += a[j];
1205 }
1206 }
1207 sta = ia[i+1];
1208 ia[i+1] = nz;
1209 }
1210 }
1211 break;
1213 {
1214 double *a = A->a;
1215 nz = 0;
1216 sta = ia[0];
1217 for (i = 0; i < A->m; i++) {
1218 for (j = sta; j < ia[i+1]; j++) {
1219 if (mask[ja[j]] < ia[i]) {
1220 ja[nz] = ja[j];
1221 a[2 * nz] = a[2 * j];
1222 a[2 * nz + 1] = a[2 * j + 1];
1223 mask[ja[j]] = nz++;
1224 } else {
1225 assert(ja[mask[ja[j]]] == ja[j]);
1226 a[2 * mask[ja[j]]] += a[2 * j];
1227 a[2 * mask[ja[j]]+1] += a[2 * j + 1];
1228 }
1229 }
1230 sta = ia[i + 1];
1231 ia[i + 1] = nz;
1232 }
1233 }
1234 break;
1236 {
1237 int *a = A->a;
1238 nz = 0;
1239 sta = ia[0];
1240 for (i = 0; i < A->m; i++){
1241 for (j = sta; j < ia[i+1]; j++){
1242 if (mask[ja[j]] < ia[i]){
1243 ja[nz] = ja[j];
1244 a[nz] = a[j];
1245 mask[ja[j]] = nz++;
1246 } else {
1247 assert(ja[mask[ja[j]]] == ja[j]);
1248 a[mask[ja[j]]] += a[j];
1249 }
1250 }
1251 sta = ia[i+1];
1252 ia[i+1] = nz;
1253 }
1254 }
1255 break;
1257 {
1258 nz = 0;
1259 sta = ia[0];
1260 for (i = 0; i < A->m; i++){
1261 for (j = sta; j < ia[i+1]; j++){
1262 if (mask[ja[j]] < ia[i]){
1263 ja[nz] = ja[j];
1264 mask[ja[j]] = nz++;
1265 } else {
1266 assert(ja[mask[ja[j]]] == ja[j]);
1267 }
1268 }
1269 sta = ia[i+1];
1270 ia[i+1] = nz;
1271 }
1272 }
1273 break;
1274 default:
1275 free(mask);
1276 return NULL;
1277 }
1278 A->nz = nz;
1279 free(mask);
1280 return A;
1281}
1282
1284 int jcn, const void *val) {
1285 int nz, nzmax;
1286
1287 static const int nentries = 1;
1288
1289 assert(A->format == FORMAT_COORD);
1290 nz = A->nz;
1291
1292 if (nz + nentries >= A->nzmax){
1293 nzmax = nz + nentries;
1294 nzmax += 10;
1295 A = SparseMatrix_realloc(A, nzmax);
1296 }
1297 A->ia[nz] = irn;
1298 A->ja[nz] = jcn;
1299 if (A->size) memcpy((char*) A->a + ((size_t)nz)*A->size/sizeof(char), val, A->size*((size_t)nentries));
1300 if (irn >= A->m) A->m = irn + 1;
1301 if (jcn >= A->n) A->n = jcn + 1;
1302 A->nz += nentries;
1303 return A;
1304}
1305
1306
1308 int i, j, *ia, *ja, nz, sta;
1309
1310 if (!A) return A;
1311
1312 nz = 0;
1313 ia = A->ia;
1314 ja = A->ja;
1315 sta = ia[0];
1316 switch (A->type){
1317 case MATRIX_TYPE_REAL:{
1318 double *a = A->a;
1319 for (i = 0; i < A->m; i++){
1320 for (j = sta; j < ia[i+1]; j++){
1321 if (ja[j] != i){
1322 ja[nz] = ja[j];
1323 a[nz++] = a[j];
1324 }
1325 }
1326 sta = ia[i+1];
1327 ia[i+1] = nz;
1328 }
1329 A->nz = nz;
1330 break;
1331 }
1332 case MATRIX_TYPE_COMPLEX:{
1333 double *a = A->a;
1334 for (i = 0; i < A->m; i++){
1335 for (j = sta; j < ia[i+1]; j++){
1336 if (ja[j] != i){
1337 ja[nz] = ja[j];
1338 a[2*nz] = a[2*j];
1339 a[2*nz+1] = a[2*j+1];
1340 nz++;
1341 }
1342 }
1343 sta = ia[i+1];
1344 ia[i+1] = nz;
1345 }
1346 A->nz = nz;
1347 break;
1348 }
1349 case MATRIX_TYPE_INTEGER:{
1350 int *a = A->a;
1351 for (i = 0; i < A->m; i++){
1352 for (j = sta; j < ia[i+1]; j++){
1353 if (ja[j] != i){
1354 ja[nz] = ja[j];
1355 a[nz++] = a[j];
1356 }
1357 }
1358 sta = ia[i+1];
1359 ia[i+1] = nz;
1360 }
1361 A->nz = nz;
1362 break;
1363 }
1364 case MATRIX_TYPE_PATTERN:{
1365 for (i = 0; i < A->m; i++){
1366 for (j = sta; j < ia[i+1]; j++){
1367 if (ja[j] != i){
1368 ja[nz++] = ja[j];
1369 }
1370 }
1371 sta = ia[i+1];
1372 ia[i+1] = nz;
1373 }
1374 A->nz = nz;
1375 break;
1376 }
1378 return NULL;
1379 default:
1380 return NULL;
1381 }
1382
1383 return A;
1384}
1385
1386
1387SparseMatrix SparseMatrix_remove_upper(SparseMatrix A){/* remove diag and upper diag */
1388 int i, j, *ia, *ja, nz, sta;
1389
1390 if (!A) return A;
1391
1392 nz = 0;
1393 ia = A->ia;
1394 ja = A->ja;
1395 sta = ia[0];
1396 switch (A->type){
1397 case MATRIX_TYPE_REAL:{
1398 double *a = A->a;
1399 for (i = 0; i < A->m; i++){
1400 for (j = sta; j < ia[i+1]; j++){
1401 if (ja[j] < i){
1402 ja[nz] = ja[j];
1403 a[nz++] = a[j];
1404 }
1405 }
1406 sta = ia[i+1];
1407 ia[i+1] = nz;
1408 }
1409 A->nz = nz;
1410 break;
1411 }
1412 case MATRIX_TYPE_COMPLEX:{
1413 double *a = A->a;
1414 for (i = 0; i < A->m; i++){
1415 for (j = sta; j < ia[i+1]; j++){
1416 if (ja[j] < i){
1417 ja[nz] = ja[j];
1418 a[2*nz] = a[2*j];
1419 a[2*nz+1] = a[2*j+1];
1420 nz++;
1421 }
1422 }
1423 sta = ia[i+1];
1424 ia[i+1] = nz;
1425 }
1426 A->nz = nz;
1427 break;
1428 }
1429 case MATRIX_TYPE_INTEGER:{
1430 int *a = A->a;
1431 for (i = 0; i < A->m; i++){
1432 for (j = sta; j < ia[i+1]; j++){
1433 if (ja[j] < i){
1434 ja[nz] = ja[j];
1435 a[nz++] = a[j];
1436 }
1437 }
1438 sta = ia[i+1];
1439 ia[i+1] = nz;
1440 }
1441 A->nz = nz;
1442 break;
1443 }
1444 case MATRIX_TYPE_PATTERN:{
1445 for (i = 0; i < A->m; i++){
1446 for (j = sta; j < ia[i+1]; j++){
1447 if (ja[j] < i){
1448 ja[nz++] = ja[j];
1449 }
1450 }
1451 sta = ia[i+1];
1452 ia[i+1] = nz;
1453 }
1454 A->nz = nz;
1455 break;
1456 }
1458 return NULL;
1459 default:
1460 return NULL;
1461 }
1462
1463 A->is_pattern_symmetric = false;
1464 A->is_symmetric = false;
1465 return A;
1466}
1467
1468
1469
1470
1472 int i, j, *ia, *ja;
1473 double deg;
1474
1475 if (!A) return A;
1476
1477 ia = A->ia;
1478 ja = A->ja;
1479 switch (A->type){
1480 case MATRIX_TYPE_REAL:{
1481 double *a = A->a;
1482 for (i = 0; i < A->m; i++){
1483 deg = ia[i+1] - ia[i];
1484 for (j = ia[i]; j < ia[i+1]; j++){
1485 a[j] = a[j]/deg;
1486 }
1487 }
1488 break;
1489 }
1490 case MATRIX_TYPE_COMPLEX:{
1491 double *a = A->a;
1492 for (i = 0; i < A->m; i++){
1493 deg = ia[i+1] - ia[i];
1494 for (j = ia[i]; j < ia[i+1]; j++){
1495 if (ja[j] != i){
1496 a[2*j] = a[2*j]/deg;
1497 a[2*j+1] = a[2*j+1]/deg;
1498 }
1499 }
1500 }
1501 break;
1502 }
1503 case MATRIX_TYPE_INTEGER:{
1504 assert(0);/* this operation would not make sense for int matrix */
1505 break;
1506 }
1507 case MATRIX_TYPE_PATTERN:{
1508 break;
1509 }
1511 return NULL;
1512 default:
1513 return NULL;
1514 }
1515
1516 return A;
1517}
1518
1519
1521 /* symmetric, all entries to 1, diaginal removed */
1522 int i, *ia, *ja, nz, m, n;
1523 double *a;
1525
1526 if (!A) return A;
1527
1528 nz = A->nz;
1529 ia = A->ia;
1530 ja = A->ja;
1531 n = A->n;
1532 m = A->m;
1533
1534 if (n != m) return NULL;
1535
1537
1538 memcpy(B->ia, ia, sizeof(int)*((size_t)(m+1)));
1539 memcpy(B->ja, ja, sizeof(int)*((size_t)nz));
1540 B->nz = A->nz;
1541
1542 A = SparseMatrix_symmetrize(B, true);
1545 A->a = gv_calloc((size_t)A->nz, sizeof(double));
1546 a = A->a;
1547 for (i = 0; i < A->nz; i++) a[i] = 1.;
1548 A->type = MATRIX_TYPE_REAL;
1549 A->size = sizeof(double);
1550 return A;
1551}
1552
1554 int i, j;
1555 double *a;
1556
1557
1558 if (!A) return A;
1559 if (A->format != FORMAT_CSR && A->type != MATRIX_TYPE_REAL) {
1560#ifdef DEBUG
1561 printf("only CSR and real matrix supported.\n");
1562#endif
1563 return A;
1564 }
1565
1566
1567 a = A->a;
1568 for (i = 0; i < A->m; i++){
1569 for (j = A->ia[i]; j < A->ia[i+1]; j++){
1570 a[j] = fun(a[j]);
1571 }
1572 }
1573 return A;
1574}
1575
1578 if (!A) return A;
1579 B = SparseMatrix_general_new(A->m, A->n, A->nz, A->type, A->size, A->format);
1580 memcpy(B->ia, A->ia, sizeof(int)*((size_t)(A->m+1)));
1581 if (A->ia[A->m] != 0) {
1582 memcpy(B->ja, A->ja, sizeof(int)*((size_t)(A->ia[A->m])));
1583 }
1584 if (A->a) memcpy(B->a, A->a, A->size*((size_t)A->nz));
1585 B->is_pattern_symmetric = A->is_pattern_symmetric;
1586 B->is_symmetric = A->is_symmetric;
1587 B->is_undirected = A->is_undirected;
1588 B->nz = A->nz;
1589 return B;
1590}
1591
1593
1594 int i, j, m = A->m, *ia = A->ia, *ja = A->ja;
1595
1596 for (i = 0; i < m; i++){
1597 for (j = ia[i]; j < ia[i+1]; j++){
1598 if (i == ja[j]) return true;
1599 }
1600 }
1601 return false;
1602}
1603
1604static void SparseMatrix_level_sets(SparseMatrix A, int root, int *nlevel,
1605 int **levelset_ptr, int **levelset,
1606 int **mask, bool reinitialize_mask) {
1607 /* mask is assumed to be initialized to negative if provided.
1608 . On exit, mask = levels for visited nodes (1 for root, 2 for its neighbors, etc),
1609 . unless reinitialize_mask is true, in which case mask = -1.
1610 A: the graph, undirected
1611 root: starting node
1612 nlevel: max distance to root from any node (in the connected comp)
1613 levelset_ptr, levelset: the level sets
1614 */
1615 int i, j, sta = 0, sto = 1, nz, ii;
1616 int m = A->m, *ia = A->ia, *ja = A->ja;
1617
1618 if (!(*levelset_ptr)) *levelset_ptr = gv_calloc((size_t)(m + 2), sizeof(int));
1619 if (!(*levelset)) *levelset = gv_calloc((size_t)m, sizeof(int));
1620 if (!(*mask)) {
1621 *mask = gv_calloc((size_t)m, sizeof(int));
1622 for (i = 0; i < m; i++) (*mask)[i] = UNMASKED;
1623 }
1624
1625 *nlevel = 0;
1626 assert(root >= 0 && root < m);
1627 (*levelset_ptr)[0] = 0;
1628 (*levelset_ptr)[1] = 1;
1629 (*levelset)[0] = root;
1630 (*mask)[root] = 1;
1631 *nlevel = 1;
1632 nz = 1;
1633 sta = 0; sto = 1;
1634 while (sto > sta){
1635 for (i = sta; i < sto; i++){
1636 ii = (*levelset)[i];
1637 for (j = ia[ii]; j < ia[ii+1]; j++){
1638 if (ii == ja[j]) continue;
1639 if ((*mask)[ja[j]] < 0){
1640 (*levelset)[nz++] = ja[j];
1641 (*mask)[ja[j]] = *nlevel + 1;
1642 }
1643 }
1644 }
1645 (*levelset_ptr)[++(*nlevel)] = nz;
1646 sta = sto;
1647 sto = nz;
1648 }
1649 (*nlevel)--;
1650 if (reinitialize_mask) for (i = 0; i < (*levelset_ptr)[*nlevel]; i++) (*mask)[(*levelset)[i]] = UNMASKED;
1651}
1652
1654 int **comps) {
1655 SparseMatrix A = A0;
1656 int *levelset_ptr = NULL, *levelset = NULL, *mask = NULL, nlevel;
1657 int m = A->m, i, nn;
1658
1659 if (!SparseMatrix_is_symmetric(A, true)){
1660 A = SparseMatrix_symmetrize(A, true);
1661 }
1662 int *comps_ptr = gv_calloc((size_t)(m + 1), sizeof(int));
1663
1664 *ncomp = 0;
1665 comps_ptr[0] = 0;
1666 for (i = 0; i < m; i++){
1667 if (i == 0 || mask[i] < 0) {
1668 SparseMatrix_level_sets(A, i, &nlevel, &levelset_ptr, &levelset, &mask, false);
1669 if (i == 0) *comps = levelset;
1670 nn = levelset_ptr[nlevel];
1671 levelset += nn;
1672 comps_ptr[(*ncomp)+1] = comps_ptr[(*ncomp)] + nn;
1673 (*ncomp)++;
1674 }
1675
1676 }
1677 if (A != A0) SparseMatrix_delete(A);
1678 free(levelset_ptr);
1679
1680 free(mask);
1681 return comps_ptr;
1682}
1683
1684void SparseMatrix_decompose_to_supervariables(SparseMatrix A, int *ncluster, int **cluster, int **clusterp){
1685 /* nodes for a super variable if they share exactly the same neighbors. This is know as modules in graph theory.
1686 We work on columns only and columns with the same pattern are grouped as a super variable
1687 */
1688 int *ia = A->ia, *ja = A->ja, n = A->n, m = A->m;
1689 int *super = NULL, *nsuper = NULL, i, j, *mask = NULL, isup, *newmap, isuper;
1690
1691 super = gv_calloc((size_t)n, sizeof(int));
1692 nsuper = gv_calloc((size_t)(n + 1), sizeof(int));
1693 mask = gv_calloc((size_t)n, sizeof(int));
1694 newmap = gv_calloc((size_t)n, sizeof(int));
1695 nsuper++;
1696
1697 isup = 0;
1698 for (i = 0; i < n; i++) super[i] = isup;/* every node belongs to super variable 0 by default */
1699 nsuper[0] = n;
1700 for (i = 0; i < n; i++) mask[i] = -1;
1701 isup++;
1702
1703 for (i = 0; i < m; i++){
1704#ifdef DEBUG_PRINT1
1705 printf("\n");
1706 printf("doing row %d-----\n",i+1);
1707#endif
1708 for (j = ia[i]; j < ia[i+1]; j++){
1709 isuper = super[ja[j]];
1710 nsuper[isuper]--;/* those entries will move to a different super vars*/
1711 }
1712 for (j = ia[i]; j < ia[i+1]; j++){
1713 isuper = super[ja[j]];
1714 if (mask[isuper] < i){
1715 mask[isuper] = i;
1716 if (nsuper[isuper] == 0){/* all nodes in the isuper group exist in this row */
1717#ifdef DEBUG_PRINT1
1718 printf("node %d keep super node id %d\n",ja[j]+1,isuper+1);
1719#endif
1720 nsuper[isuper] = 1;
1721 newmap[isuper] = isuper;
1722 } else {
1723 newmap[isuper] = isup;
1724 nsuper[isup] = 1;
1725#ifdef DEBUG_PRINT1
1726 printf("make node %d into supernode %d\n",ja[j]+1,isup+1);
1727#endif
1728 super[ja[j]] = isup++;
1729 }
1730 } else {
1731#ifdef DEBUG_PRINT1
1732 printf("node %d join super node %d\n",ja[j]+1,newmap[isuper]+1);
1733#endif
1734 super[ja[j]] = newmap[isuper];
1735 nsuper[newmap[isuper]]++;
1736 }
1737 }
1738#ifdef DEBUG_PRINT1
1739 printf("nsuper=");
1740 for (j = 0; j < isup; j++) printf("(%d,%d),",j+1,nsuper[j]);
1741 printf("\n");
1742#endif
1743 }
1744#ifdef DEBUG_PRINT1
1745 for (i = 0; i < n; i++){
1746 printf("node %d is in supernode %d\n",i, super[i]);
1747 }
1748#endif
1749#ifdef PRINT
1750 fprintf(stderr, "n = %d, nsup = %d\n",n,isup);
1751#endif
1752 /* now accumulate super nodes */
1753 nsuper--;
1754 nsuper[0] = 0;
1755 for (i = 0; i < isup; i++) nsuper[i+1] += nsuper[i];
1756
1757 *cluster = newmap;
1758 for (i = 0; i < n; i++){
1759 isuper = super[i];
1760 (*cluster)[nsuper[isuper]++] = i;
1761 }
1762 for (i = isup; i > 0; i--) nsuper[i] = nsuper[i-1];
1763 nsuper[0] = 0;
1764 *clusterp = nsuper;
1765 *ncluster = isup;
1766
1767#ifdef PRINT
1768 for (i = 0; i < *ncluster; i++){
1769 printf("{");
1770 for (j = (*clusterp)[i]; j < (*clusterp)[i+1]; j++){
1771 printf("%d, ",(*cluster)[j]);
1772 }
1773 printf("},");
1774 }
1775 printf("\n");
1776#endif
1777
1778 free(mask);
1779 free(super);
1780}
1781
1783 /* convert matrix A to an augmente dmatrix {{0,A},{A^T,0}} */
1784 int *irn = NULL, *jcn = NULL;
1785 void *val = NULL;
1786 int nz = A->nz, type = A->type;
1787 int m = A->m, n = A->n, i, j;
1789 if (!A) return NULL;
1790 if (nz > 0){
1791 irn = gv_calloc((size_t)nz * 2, sizeof(int));
1792 jcn = gv_calloc((size_t)nz * 2, sizeof(int));
1793 }
1794
1795 if (A->a){
1796 assert(A->size != 0 && nz > 0);
1797 val = gv_calloc(2 * (size_t)nz, A->size);
1798 memcpy(val, A->a, A->size*((size_t)nz));
1799 memcpy(((char*) val) + ((size_t)nz)*A->size, A->a, A->size*((size_t)nz));
1800 }
1801
1802 nz = 0;
1803 for (i = 0; i < m; i++){
1804 for (j = (A->ia)[i]; j < (A->ia)[i+1]; j++){
1805 irn[nz] = i;
1806 jcn[nz++] = (A->ja)[j] + m;
1807 }
1808 }
1809 for (i = 0; i < m; i++){
1810 for (j = (A->ia)[i]; j < (A->ia)[i+1]; j++){
1811 jcn[nz] = i;
1812 irn[nz++] = (A->ja)[j] + m;
1813 }
1814 }
1815
1816 B = SparseMatrix_from_coordinate_arrays(nz, m + n, m + n, irn, jcn, val, type, A->size);
1817 B->is_symmetric = true;
1818 B->is_pattern_symmetric = true;
1819 free(irn);
1820 free(jcn);
1821 free(val);
1822 return B;
1823}
1824
1827 switch (bipartite_options){
1828 case BIPARTITE_RECT:
1829 if (A->m == A->n) return A;
1830 break;
1832 if (A->m == A->n && SparseMatrix_is_symmetric(A, true)) return A;
1833 break;
1834 case BIPARTITE_UNSYM:
1835 if (A->m == A->n && SparseMatrix_is_symmetric(A, false)) return A;
1836 break;
1837 case BIPARTITE_ALWAYS:
1838 break;
1839 default:
1840 assert(0);
1841 }
1844 return B;
1845}
1846
1847SparseMatrix SparseMatrix_get_submatrix(SparseMatrix A, int nrow, int ncol, int *rindices, int *cindices){
1848 /* get the submatrix from row/columns indices[0,...,l-1].
1849 row rindices[i] will be the new row i
1850 column cindices[i] will be the new column i.
1851 if rindices = NULL, it is assume that 1 -- nrow is needed. Same for cindices/ncol.
1852 */
1853 int nz = 0, i, j, *irn, *jcn, *ia = A->ia, *ja = A->ja, m = A->m, n = A->n;
1854 int *cmask, *rmask;
1855 void *v = NULL;
1857 int irow = 0, icol = 0;
1858
1859 if (nrow <= 0 || ncol <= 0) return NULL;
1860
1861
1862
1863 rmask = gv_calloc((size_t)m, sizeof(int));
1864 cmask = gv_calloc((size_t)n, sizeof(int));
1865 for (i = 0; i < m; i++) rmask[i] = -1;
1866 for (i = 0; i < n; i++) cmask[i] = -1;
1867
1868 if (rindices){
1869 for (i = 0; i < nrow; i++) {
1870 if (rindices[i] >= 0 && rindices[i] < m){
1871 rmask[rindices[i]] = irow++;
1872 }
1873 }
1874 } else {
1875 for (i = 0; i < nrow; i++) {
1876 rmask[i] = irow++;
1877 }
1878 }
1879
1880 if (cindices){
1881 for (i = 0; i < ncol; i++) {
1882 if (cindices[i] >= 0 && cindices[i] < n){
1883 cmask[cindices[i]] = icol++;
1884 }
1885 }
1886 } else {
1887 for (i = 0; i < ncol; i++) {
1888 cmask[i] = icol++;
1889 }
1890 }
1891
1892 for (i = 0; i < m; i++){
1893 if (rmask[i] < 0) continue;
1894 for (j = ia[i]; j < ia[i+1]; j++){
1895 if (cmask[ja[j]] < 0) continue;
1896 nz++;
1897 }
1898 }
1899
1900
1901 switch (A->type){
1902 case MATRIX_TYPE_REAL:{
1903 double *a = A->a;
1904 double *val;
1905 irn = gv_calloc((size_t)nz, sizeof(int));
1906 jcn = gv_calloc((size_t)nz, sizeof(int));
1907 val = gv_calloc((size_t)nz, sizeof(double));
1908
1909 nz = 0;
1910 for (i = 0; i < m; i++){
1911 if (rmask[i] < 0) continue;
1912 for (j = ia[i]; j < ia[i+1]; j++){
1913 if (cmask[ja[j]] < 0) continue;
1914 irn[nz] = rmask[i];
1915 jcn[nz] = cmask[ja[j]];
1916 val[nz++] = a[j];
1917 }
1918 }
1919 v = val;
1920 break;
1921 }
1922 case MATRIX_TYPE_COMPLEX:{
1923 double *a = A->a;
1924 double *val;
1925
1926 irn = gv_calloc((size_t)nz, sizeof(int));
1927 jcn = gv_calloc((size_t)nz, sizeof(int));
1928 val = gv_calloc(2 * (size_t)nz, sizeof(double));
1929
1930 nz = 0;
1931 for (i = 0; i < m; i++){
1932 if (rmask[i] < 0) continue;
1933 for (j = ia[i]; j < ia[i+1]; j++){
1934 if (cmask[ja[j]] < 0) continue;
1935 irn[nz] = rmask[i];
1936 jcn[nz] = cmask[ja[j]];
1937 val[2*nz] = a[2*j];
1938 val[2*nz+1] = a[2*j+1];
1939 nz++;
1940 }
1941 }
1942 v = val;
1943 break;
1944 }
1945 case MATRIX_TYPE_INTEGER:{
1946 int *a = A->a;
1947 int *val;
1948
1949 irn = gv_calloc((size_t)nz, sizeof(int));
1950 jcn = gv_calloc((size_t)nz, sizeof(int));
1951 val = gv_calloc((size_t)nz, sizeof(int));
1952
1953 nz = 0;
1954 for (i = 0; i < m; i++){
1955 if (rmask[i] < 0) continue;
1956 for (j = ia[i]; j < ia[i+1]; j++){
1957 if (cmask[ja[j]] < 0) continue;
1958 irn[nz] = rmask[i];
1959 jcn[nz] = cmask[ja[j]];
1960 val[nz] = a[j];
1961 nz++;
1962 }
1963 }
1964 v = val;
1965 break;
1966 }
1968 irn = gv_calloc((size_t)nz, sizeof(int));
1969 jcn = gv_calloc((size_t)nz, sizeof(int));
1970 nz = 0;
1971 for (i = 0; i < m; i++){
1972 if (rmask[i] < 0) continue;
1973 for (j = ia[i]; j < ia[i+1]; j++){
1974 if (cmask[ja[j]] < 0) continue;
1975 irn[nz] = rmask[i];
1976 jcn[nz++] = cmask[ja[j]];
1977 }
1978 }
1979 break;
1981 free(rmask);
1982 free(cmask);
1983 return NULL;
1984 default:
1985 free(rmask);
1986 free(cmask);
1987 return NULL;
1988 }
1989
1990 B = SparseMatrix_from_coordinate_arrays(nz, nrow, ncol, irn, jcn, v, A->type, A->size);
1991 free(cmask);
1992 free(rmask);
1993 free(irn);
1994 free(jcn);
1995 if (v) free(v);
1996
1997
1998 return B;
1999
2000}
2001
2003 double *a;
2004 int i;
2005
2006 free(A->a);
2007 A->a = gv_calloc((size_t)A->nz, sizeof(double));
2008 a = A->a;
2009 for (i = 0; i < A->nz; i++) a[i] = 1.;
2010 A->type = MATRIX_TYPE_REAL;
2011 A->size = sizeof(double);
2012 return A;
2013
2014}
2015
2016SparseMatrix SparseMatrix_from_dense(int m, int n, double *x){
2017 /* wrap a mxn matrix into a sparse matrix. the {i,j} entry of the matrix is in x[i*n+j], 0<=i<m; 0<=j<n */
2018 int i, j, *ja;
2019 double *a;
2021
2022 A->ia[0] = 0;
2023 for (i = 1; i <= m; i++) (A->ia)[i] = (A->ia)[i-1] + n;
2024
2025 ja = A->ja;
2026 a = A->a;
2027 for (i = 0; i < m; i++){
2028 for (j = 0; j < n; j++) {
2029 ja[j] = j;
2030 a[j] = x[i*n+j];
2031 }
2032 ja += n; a += j;
2033 }
2034 A->nz = m*n;
2035 return A;
2036
2037}
2038
2040 /*
2041 Input:
2042 D: the graph. Entry values are unused.
2043 Output:
2044 dist: of dimension nxn, dist[i*n+j] gives the distance of node i to j.
2045 */
2046 SparseMatrix D = D0;
2047 int m = D->m, n = D->n;
2048 int *levelset_ptr = NULL, *levelset = NULL, *mask = NULL;
2049 int i, j, k, nlevel;
2050
2051 if (!SparseMatrix_is_symmetric(D, false)){
2052 D = SparseMatrix_symmetrize(D, false);
2053 }
2054
2055 assert(m == n);
2056 (void)m;
2057
2058 if (!(*dist0)) *dist0 = gv_calloc(n * n, sizeof(double));
2059 for (i = 0; i < n*n; i++) (*dist0)[i] = -1;
2060
2061 for (k = 0; k < n; k++) {
2062 SparseMatrix_level_sets(D, k, &nlevel, &levelset_ptr, &levelset, &mask, true);
2063 assert(levelset_ptr[nlevel] == n);
2064 for (i = 0; i < nlevel; i++) {
2065 for (j = levelset_ptr[i]; j < levelset_ptr[i+1]; j++) {
2066 (*dist0)[k*n+levelset[j]] = i;
2067 }
2068 }
2069 }
2070
2071 free(levelset_ptr);
2072 free(levelset);
2073 free(mask);
2074
2075 if (D != D0) SparseMatrix_delete(D);
2076}
void SparseMatrix_distance_matrix(SparseMatrix D0, double **dist0)
static SparseMatrix SparseMatrix_realloc(SparseMatrix A, int nz)
void SparseMatrix_decompose_to_supervariables(SparseMatrix A, int *ncluster, int **cluster, int **clusterp)
SparseMatrix SparseMatrix_from_coordinate_format(SparseMatrix A)
SparseMatrix SparseMatrix_transpose(SparseMatrix A)
SparseMatrix SparseMatrix_remove_upper(SparseMatrix A)
SparseMatrix SparseMatrix_get_submatrix(SparseMatrix A, int nrow, int ncol, int *rindices, int *cindices)
SparseMatrix SparseMatrix_symmetrize(SparseMatrix A, bool pattern_symmetric_only)
SparseMatrix SparseMatrix_general_new(int m, int n, int nz, int type, size_t sz, int format)
SparseMatrix SparseMatrix_get_augmented(SparseMatrix A)
static size_t size_of_matrix_type(int type)
void SparseMatrix_multiply_dense(SparseMatrix A, const double *v, double *res, int dim)
SparseMatrix SparseMatrix_coordinate_form_add_entry(SparseMatrix A, int irn, int jcn, const void *val)
static SparseMatrix SparseMatrix_from_coordinate_arrays_internal(int nz, int m, int n, int *irn, int *jcn, const void *val0, int type, size_t sz, int sum_repeated)
bool SparseMatrix_is_symmetric(SparseMatrix A, bool test_pattern_symmetry_only)
SparseMatrix SparseMatrix_to_square_matrix(SparseMatrix A, int bipartite_options)
void SparseMatrix_multiply_vector(SparseMatrix A, double *v, double **res)
SparseMatrix SparseMatrix_multiply(SparseMatrix A, SparseMatrix B)
SparseMatrix SparseMatrix_divide_row_by_degree(SparseMatrix A)
void SparseMatrix_export(FILE *f, SparseMatrix A)
static void SparseMatrix_export_csr(FILE *f, SparseMatrix A)
SparseMatrix SparseMatrix_from_coordinate_arrays_not_compacted(int nz, int m, int n, int *irn, int *jcn, void *val0, int type, size_t sz)
SparseMatrix SparseMatrix_from_coordinate_arrays(int nz, int m, int n, int *irn, int *jcn, const void *val, int type, size_t sz)
static void SparseMatrix_export_coord(FILE *f, SparseMatrix A)
void SparseMatrix_delete(SparseMatrix A)
SparseMatrix SparseMatrix_make_undirected(SparseMatrix A)
static SparseMatrix SparseMatrix_alloc(SparseMatrix A, int nz)
SparseMatrix SparseMatrix_copy(SparseMatrix A)
SparseMatrix SparseMatrix_set_entries_to_real_one(SparseMatrix A)
static void SparseMatrix_level_sets(SparseMatrix A, int root, int *nlevel, int **levelset_ptr, int **levelset, int **mask, bool reinitialize_mask)
SparseMatrix SparseMatrix_get_real_adjacency_matrix_symmetrized(SparseMatrix A)
SparseMatrix SparseMatrix_sort(SparseMatrix A)
SparseMatrix SparseMatrix_sum_repeat_entries(SparseMatrix A)
SparseMatrix SparseMatrix_add(SparseMatrix A, SparseMatrix B)
SparseMatrix SparseMatrix_multiply3(SparseMatrix A, SparseMatrix B, SparseMatrix C)
SparseMatrix SparseMatrix_apply_fun(SparseMatrix A, double(*fun)(double x))
bool SparseMatrix_has_diagonal(SparseMatrix A)
static SparseMatrix SparseMatrix_init(int m, int n, int type, size_t sz, int format)
int * SparseMatrix_weakly_connected_components(SparseMatrix A0, int *ncomp, int **comps)
SparseMatrix SparseMatrix_from_coordinate_format_not_compacted(SparseMatrix A)
SparseMatrix SparseMatrix_remove_diagonal(SparseMatrix A)
SparseMatrix SparseMatrix_new(int m, int n, int nz, int type, int format)
SparseMatrix SparseMatrix_from_dense(int m, int n, double *x)
@ MATRIX_TYPE_REAL
@ MATRIX_TYPE_UNKNOWN
@ MATRIX_TYPE_PATTERN
@ MATRIX_TYPE_COMPLEX
@ MATRIX_TYPE_INTEGER
#define SYMMETRY_EPSILON
@ UNMASKED
@ SUM_REPEATED_ALL
@ SUM_REPEATED_NONE
@ FORMAT_COORD
@ FORMAT_CSR
@ BIPARTITE_PATTERN_UNSYM
@ BIPARTITE_UNSYM
@ BIPARTITE_RECT
@ BIPARTITE_ALWAYS
Memory allocation wrappers that exit on failure.
static void * gv_recalloc(void *ptr, size_t old_nmemb, size_t new_nmemb, size_t size)
Definition alloc.h:73
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
static void * gv_alloc(size_t size)
Definition alloc.h:47
expr procedure type
Definition exparse.y:208
#define A(n, t)
Definition expr.h:76
void free(void *)
node NULL
Definition grammar.y:181
static uint64_t id
Definition gv2gml.c:40
GVIO_API const char * format
Definition gvio.h:51
#define B
Definition hierarchy.c:118
#define D
Definition hierarchy.c:120
static const int dim
#define C
Definition pack.c:30
#define RETURN(v)
Definition strmatch.c:144