1 //------------------------------------------------------------------------------
2 // GB_mex_triple_mxm: C = A*B*E
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 #include "GB_mex.h"
11 
12 #define USAGE "C = GB_mex_triple_mxm (semiring, A, B, E, desc)"
13 
14 #define FREE_ALL                                    \
15 {                                                   \
16     GrB_Matrix_free_(&A) ;                          \
17     GrB_Matrix_free_(&B) ;                          \
18     GrB_Matrix_free_(&C) ;                          \
19     GrB_Matrix_free_(&E) ;                          \
20     GrB_Matrix_free_(&T) ;                          \
21     if (semiring != Complex_plus_times)             \
22     {                                               \
23         if (semiring != NULL)                       \
24         {                                           \
25             GrB_Monoid_free_(&(semiring->add)) ;    \
26         }                                           \
27         GrB_Semiring_free_(&semiring) ;             \
28     }                                               \
29     GrB_Descriptor_free_(&desc) ;                   \
30     GB_mx_put_global (true) ;                       \
31 }
32 
mexFunction(int nargout,mxArray * pargout[],int nargin,const mxArray * pargin[])33 void mexFunction
34 (
35     int nargout,
36     mxArray *pargout [ ],
37     int nargin,
38     const mxArray *pargin [ ]
39 )
40 {
41 
42     bool malloc_debug = GB_mx_get_global (true) ;
43     GrB_Matrix A = NULL ;
44     GrB_Matrix B = NULL ;
45     GrB_Matrix C = NULL ;
46     GrB_Matrix E = NULL ;
47     GrB_Matrix T = NULL ;
48     GrB_Semiring semiring = NULL ;
49     GrB_Descriptor desc = NULL ;
50 
51     // check inputs
52     if (nargout > 1 || nargin < 4 || nargin > 5)
53     {
54         mexErrMsgTxt ("Usage: " USAGE) ;
55     }
56 
57     #define GET_DEEP_COPY ;
58     #define FREE_DEEP_COPY ;
59 
60     // get A (shallow copy)
61     A = GB_mx_mxArray_to_Matrix (pargin [1], "A input", false, true) ;
62     if (A == NULL)
63     {
64         FREE_ALL ;
65         mexErrMsgTxt ("A failed") ;
66     }
67 
68     // get B (shallow copy)
69     B = GB_mx_mxArray_to_Matrix (pargin [2], "B input", false, true) ;
70     if (B == NULL)
71     {
72         FREE_ALL ;
73         mexErrMsgTxt ("B failed") ;
74     }
75 
76     // get E (shallow copy)
77     E = GB_mx_mxArray_to_Matrix (pargin [3], "E input", false, true) ;
78     if (E == NULL)
79     {
80         FREE_ALL ;
81         mexErrMsgTxt ("B failed") ;
82     }
83 
84     bool user_complex = (Complex != GxB_FC64) && (A->type == Complex) ;
85 
86     // get semiring
87     if (!GB_mx_mxArray_to_Semiring (&semiring, pargin [0], "semiring",
88         A->type, user_complex))
89     {
90         FREE_ALL ;
91         mexErrMsgTxt ("semiring failed") ;
92     }
93 
94     // get desc
95     if (!GB_mx_mxArray_to_Descriptor (&desc, PARGIN (4), "desc"))
96     {
97         FREE_ALL ;
98         mexErrMsgTxt ("desc failed") ;
99     }
100 
101     // T = B*E
102     GrB_Index nrows, ncols ;
103     GrB_Matrix_nrows (&nrows, B) ;
104     GrB_Matrix_ncols (&ncols, E) ;
105     GrB_Matrix_new (&T, A->type, nrows, ncols) ;
106     GxB_Matrix_Option_set_(T, GxB_SPARSITY_CONTROL, GxB_SPARSE) ;
107     GrB_mxm (T, NULL, NULL, semiring, B, E, desc) ;
108 
109     // C = A*T
110     GrB_Matrix_ncols (&nrows, A) ;
111     GrB_Matrix_new (&C, A->type, nrows, ncols) ;
112     GrB_mxm (C, NULL, NULL, semiring, A, T, desc) ;
113 
114     // return C to MATLAB as a struct and free the GraphBLAS C
115     pargout [0] = GB_mx_Matrix_to_mxArray (&C, "C from GrB_mxm_triple", true) ;
116 
117     FREE_ALL ;
118 }
119 
120