1 //------------------------------------------------------------------------------
2 // GraphBLAS/Demo/Program/kron_demo.c: Kronkecker product
3 //------------------------------------------------------------------------------
4 
5 // SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
6 // SPDX-License-Identifier: Apache-2.0
7 
8 //------------------------------------------------------------------------------
9 
10 // Reads two graphs from two files and computes their Kronecker product,
11 // C = kron (A,B), writing the result to a file.
12 //
13 //  kron_demo A.tsv B.tsv C.tsv
14 //
15 // Where A.tsv and B.tsv are two tab- or space-delimited triplet files with
16 // 1-based indices.  Each line has the form:
17 //
18 //  i j x
19 //
20 // where A(i,j)=x is performed by GrB_Matrix_build, to construct the matrix.
21 // The dimensions of A and B are assumed to be the largest row and column
22 // indices that appear in the files.  The file C.tsv is the filename of the
23 // output file for C=kron(A,B), also with 1-based indices.
24 
25 // macro used by OK(...) to free workspace if an error occurs
26 #define FREE_ALL                            \
27     GrB_Matrix_free (&A) ;                  \
28     GrB_Matrix_free (&B) ;                  \
29     GrB_Matrix_free (&C) ;                  \
30     if (Afile != NULL) fclose (Afile) ;     \
31     if (Bfile != NULL) fclose (Bfile) ;     \
32     if (Cfile != NULL) fclose (Cfile) ;     \
33     if (I != NULL) free (I) ;               \
34     if (J != NULL) free (J) ;               \
35     if (X != NULL) free (X) ;               \
36     GrB_finalize ( ) ;
37 
38 #include "graphblas_demos.h"
39 
main(int argc,char ** argv)40 int main (int argc, char **argv)
41 {
42     //--------------------------------------------------------------------------
43     // check inputs
44     //--------------------------------------------------------------------------
45 
46     GrB_Matrix A = NULL, B = NULL, C = NULL ;
47     GrB_Index *I = NULL, *J = NULL ;
48     FILE *Afile = NULL, *Bfile = NULL, *Cfile = NULL ;
49     double *X = NULL ;
50     GrB_Info info ;
51     double tic [2], t ;
52 
53     OK (GrB_init (GrB_NONBLOCKING)) ;
54     int nthreads ;
55     OK (GxB_Global_Option_get (GxB_GLOBAL_NTHREADS, &nthreads)) ;
56     fprintf (stderr, "kron demo: nthreads %d\n", nthreads) ;
57 
58     // printf ("argc %d\n", argc) ;
59     if (argc != 4)
60     {
61         FREE_ALL ;
62         fprintf (stderr, "usage: kron_demo A.tsv B.tsv C.tsv\n") ;
63         exit (1) ;
64     }
65 
66     Afile = fopen (argv [1], "r") ;
67     Bfile = fopen (argv [2], "r") ;
68     Cfile = fopen (argv [3], "w") ;
69     if (Afile == NULL || Bfile == NULL || Cfile == NULL)
70     {
71         FREE_ALL ;
72         fprintf (stderr, "unable to read input files or create output file\n") ;
73         exit (1) ;
74     }
75 
76     //--------------------------------------------------------------------------
77     // get A and B from input files
78     //--------------------------------------------------------------------------
79 
80     // this would be faster and take less memory if GraphBLAS had a built-in
81     // read-from-file operation
82     OK (read_matrix (&A, Afile, false, false, true, false, false)) ;
83     OK (read_matrix (&B, Bfile, false, false, true, false, false)) ;
84 
85     fclose (Afile) ;
86     fclose (Bfile) ;
87     Afile = NULL ;
88     Bfile = NULL ;
89 
90     GrB_Index anrows, ancols, bnrows, bncols, anvals, bnvals ;
91     OK (GrB_Matrix_nrows (&anrows, A)) ;
92     OK (GrB_Matrix_ncols (&ancols, A)) ;
93     OK (GrB_Matrix_nvals (&anvals, A)) ;
94     OK (GrB_Matrix_nrows (&bnrows, B)) ;
95     OK (GrB_Matrix_ncols (&bncols, B)) ;
96     OK (GrB_Matrix_nvals (&bnvals, B)) ;
97 
98     //--------------------------------------------------------------------------
99     // C = kron (A,B)
100     //--------------------------------------------------------------------------
101 
102     OK (GrB_Matrix_new (&C, GrB_FP64, anrows * bnrows, ancols * bncols)) ;
103 
104     simple_tic (tic) ;
105     OK (GrB_Matrix_kronecker_BinaryOp (C, NULL, NULL,
106         GrB_TIMES_FP64, A, B, NULL)) ;
107     t = simple_toc (tic) ;
108 
109     OK (GrB_Matrix_free (&A)) ;
110     OK (GrB_Matrix_free (&B)) ;
111 
112     //--------------------------------------------------------------------------
113     // report results
114     //--------------------------------------------------------------------------
115 
116     GrB_Index cnrows, cncols, cnvals ;
117     OK (GrB_Matrix_nrows (&cnrows, C)) ;
118     OK (GrB_Matrix_ncols (&cncols, C)) ;
119     OK (GrB_Matrix_nvals (&cnvals, C)) ;
120 
121     // note that integers of type GrB_Index should be printed with the
122     // %PRIu64 format.
123 
124     fprintf (stderr, "GraphBLAS GrB_kronecker:\n"
125     "A: %" PRIu64 "-by-%" PRIu64 ", %" PRIu64 " entries.\n"
126     "B: %" PRIu64 "-by-%" PRIu64 ", %" PRIu64 " entries.\n"
127     "C: %" PRIu64 "-by-%" PRIu64 ", %" PRIu64 " entries.\n"
128     "time: %g seconds, rate: nval(C)/t = %g million/sec\n",
129     anrows, ancols, anvals,
130     bnrows, bncols, bnvals,
131     cnrows, cncols, cnvals,
132     t, 1e-6*((double) cnvals) / t) ;
133 
134     //--------------------------------------------------------------------------
135     // write C to the output file
136     //--------------------------------------------------------------------------
137 
138     // this would be faster and take less memory if GraphBLAS had a built-in
139     // write-to-file operation
140 
141     I = (GrB_Index *) malloc ((cnvals+1) * sizeof (GrB_Index)) ;
142     J = (GrB_Index *) malloc ((cnvals+1) * sizeof (GrB_Index)) ;
143     X = (double    *) malloc ((cnvals+1) * sizeof (double   )) ;
144     if (I == NULL || J == NULL || X == NULL)
145     {
146         fprintf (stderr, "out of memory\n") ;
147         FREE_ALL ;
148         exit (1) ;
149     }
150 
151     OK (GrB_Matrix_extractTuples_FP64 (I, J, X, &cnvals, C)) ;
152 
153     for (int64_t k = 0 ; k < cnvals ; k++)
154     {
155         fprintf (Cfile, "%" PRIu64 "\t%" PRIu64 "\t%.17g\n", 1 + I [k], 1 + J [k], X [k]) ;
156     }
157 
158     FREE_ALL ;
159     return (0) ;
160 }
161 
162