//------------------------------------------------------------------------------ // gbkronecker: sparse matrix Kronecker product //------------------------------------------------------------------------------ // SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved. // SPDX-License-Identifier: GPL-3.0-or-later //------------------------------------------------------------------------------ // gbkronecker is an interface to GrB_kronecker // Usage: // C = gbkronecker (op, A, B) // C = gbkronecker (op, A, B, desc) // C = gbkronecker (Cin, accum, op, A, B, desc) // C = gbkronecker (Cin, M, op, A, B, desc) // C = gbkronecker (Cin, M, accum, op, A, B, desc) // If Cin is not present then it is implicitly a matrix with no entries, of the // right size (which depends on A, B, and the descriptor). #include "gb_matlab.h" #define USAGE "usage: C = GrB.kronecker (Cin, M, accum, op, A, B, desc)" void mexFunction ( int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin [ ] ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- gb_usage (nargin >= 3 && nargin <= 7 && nargout <= 2, USAGE) ; //-------------------------------------------------------------------------- // find the arguments //-------------------------------------------------------------------------- mxArray *Matrix [4], *String [2], *Cell [2] ; base_enum_t base ; kind_enum_t kind ; GxB_Format_Value fmt ; int nmatrices, nstrings, ncells, sparsity ; GrB_Descriptor desc ; gb_get_mxargs (nargin, pargin, USAGE, Matrix, &nmatrices, String, &nstrings, Cell, &ncells, &desc, &base, &kind, &fmt, &sparsity) ; CHECK_ERROR (nmatrices < 2 || nstrings < 1 || ncells > 0, USAGE) ; //-------------------------------------------------------------------------- // get the matrices //-------------------------------------------------------------------------- GrB_Type atype, btype, ctype = NULL ; GrB_Matrix C = NULL, M = NULL, A, B ; if (nmatrices == 2) { A = gb_get_shallow (Matrix [0]) ; B = gb_get_shallow (Matrix [1]) ; } else if (nmatrices == 3) { C = gb_get_deep (Matrix [0]) ; A = gb_get_shallow (Matrix [1]) ; B = gb_get_shallow (Matrix [2]) ; } else // if (nmatrices == 4) { C = gb_get_deep (Matrix [0]) ; M = gb_get_shallow (Matrix [1]) ; A = gb_get_shallow (Matrix [2]) ; B = gb_get_shallow (Matrix [3]) ; } OK (GxB_Matrix_type (&atype, A)) ; OK (GxB_Matrix_type (&btype, B)) ; if (C != NULL) { OK (GxB_Matrix_type (&ctype, C)) ; } //-------------------------------------------------------------------------- // get the operators //-------------------------------------------------------------------------- GrB_BinaryOp accum = NULL, op ; if (nstrings == 1) { op = gb_mxstring_to_binop (String [0], atype, btype) ; } else { // if accum appears, then Cin must also appear CHECK_ERROR (C == NULL, USAGE) ; accum = gb_mxstring_to_binop (String [0], ctype, ctype) ; op = gb_mxstring_to_binop (String [1], atype, btype) ; } //-------------------------------------------------------------------------- // construct C if not present on input //-------------------------------------------------------------------------- // If C is NULL, then it is not present on input. // Construct C of the right size and type. if (C == NULL) { // get the descriptor contents to determine if A and B are transposed GrB_Desc_Value in0, in1 ; OK (GxB_Desc_get (desc, GrB_INP0, &in0)) ; OK (GxB_Desc_get (desc, GrB_INP1, &in1)) ; bool A_transpose = (in0 == GrB_TRAN) ; bool B_transpose = (in1 == GrB_TRAN) ; // get the size of A and B GrB_Index anrows, ancols, bnrows, bncols ; if (A_transpose) { OK (GrB_Matrix_nrows (&ancols, A)) ; OK (GrB_Matrix_ncols (&anrows, A)) ; } else { OK (GrB_Matrix_nrows (&anrows, A)) ; OK (GrB_Matrix_ncols (&ancols, A)) ; } if (B_transpose) { OK (GrB_Matrix_nrows (&bncols, B)) ; OK (GrB_Matrix_ncols (&bnrows, B)) ; } else { OK (GrB_Matrix_nrows (&bnrows, B)) ; OK (GrB_Matrix_ncols (&bncols, B)) ; } // determine the size of C GrB_Index cnrows = anrows * bnrows ; GrB_Index cncols = ancols * bncols ; // use the ztype of the op as the type of C OK (GxB_BinaryOp_ztype (&ctype, op)) ; // create the matrix C and set its format and sparsity fmt = gb_get_format (cnrows, cncols, A, B, fmt) ; sparsity = gb_get_sparsity (A, B, sparsity) ; C = gb_new (ctype, cnrows, cncols, fmt, sparsity) ; } //-------------------------------------------------------------------------- // compute C += kron (A,B) //-------------------------------------------------------------------------- OK1 (C, GrB_Matrix_kronecker_BinaryOp (C, M, accum, op, A, B, desc)) ; //-------------------------------------------------------------------------- // free shallow copies //-------------------------------------------------------------------------- OK (GrB_Matrix_free (&M)) ; OK (GrB_Matrix_free (&A)) ; OK (GrB_Matrix_free (&B)) ; OK (GrB_Descriptor_free (&desc)) ; //-------------------------------------------------------------------------- // export the output matrix C back to MATLAB //-------------------------------------------------------------------------- pargout [0] = gb_export (&C, kind) ; pargout [1] = mxCreateDoubleScalar (kind) ; GB_WRAPUP ; }