1 //------------------------------------------------------------------------------
2 // gbvdiag: extract a diaogonal of a matrix, as a vector
3 //------------------------------------------------------------------------------
4 
5 // SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
6 // SPDX-License-Identifier: GPL-3.0-or-later
7 
8 //------------------------------------------------------------------------------
9 
10 // Usage:
11 
12 // v = gbvdiag (A, k, desc)
13 
14 #include "gb_matlab.h"
15 
16 #define USAGE "usage: v = gbvdiag (A, k, desc)"
17 
mexFunction(int nargout,mxArray * pargout[],int nargin,const mxArray * pargin[])18 void mexFunction
19 (
20     int nargout,
21     mxArray *pargout [ ],
22     int nargin,
23     const mxArray *pargin [ ]
24 )
25 {
26 
27     //--------------------------------------------------------------------------
28     // check inputs
29     //--------------------------------------------------------------------------
30 
31     gb_usage (nargin >= 1 && nargin <= 3 && nargout <= 2, USAGE) ;
32 
33     //--------------------------------------------------------------------------
34     // get the descriptor
35     //--------------------------------------------------------------------------
36 
37     base_enum_t base ;
38     kind_enum_t kind ;
39     GxB_Format_Value fmt ;
40     int sparsity ;
41     GrB_Descriptor desc = NULL ;
42     desc = gb_mxarray_to_descriptor (pargin [nargin-1], &kind, &fmt,
43         &sparsity, &base) ;
44     // if present, remove the descriptor from consideration
45     if (desc != NULL) nargin-- ;
46 
47     //--------------------------------------------------------------------------
48     // get the inputs
49     //--------------------------------------------------------------------------
50 
51     GrB_Matrix V = NULL ;
52     GrB_Matrix A = gb_get_shallow (pargin [0]) ;
53     int64_t k = 0 ;
54 
55     if (nargin > 1)
56     {
57         CHECK_ERROR (!gb_mxarray_is_scalar (pargin [1]), "k must be a scalar") ;
58         double x = mxGetScalar (pargin [1]) ;
59         k = (int64_t) x ;
60         CHECK_ERROR ((double) k != x, "k must be an integer scalar") ;
61     }
62 
63     //--------------------------------------------------------------------------
64     // construct V
65     //--------------------------------------------------------------------------
66 
67     GrB_Type vtype = NULL ;
68     int64_t n, nrows, ncols ;
69     OK (GxB_Matrix_type (&vtype, A)) ;
70     OK (GrB_Matrix_nrows (&nrows, A)) ;
71     OK (GrB_Matrix_ncols (&ncols, A)) ;
72 
73     if (k >= ncols || k <= -nrows)
74     {
75         // output vector V must have zero length
76         n = 0 ;
77     }
78     else if (k >= 0)
79     {
80         // if k is in range 0 to n-1, V must have length min (m,n-k)
81         n = GB_IMIN (nrows, ncols - k) ;
82     }
83     else
84     {
85         // if k is in range -1 to -m+1, V must have length min (m+k,n)
86         n = GB_IMIN (nrows + k, ncols) ;
87     }
88 
89     V = gb_new (vtype, n, 1, GxB_BY_COL, 0) ;
90 
91     //--------------------------------------------------------------------------
92     // compute v = diag (A, k)
93     //--------------------------------------------------------------------------
94 
95     OK1 (V, GxB_Vector_diag ((GrB_Vector) V, A, k, desc)) ;
96 
97     //--------------------------------------------------------------------------
98     // free shallow copies
99     //--------------------------------------------------------------------------
100 
101     OK (GrB_Matrix_free (&A)) ;
102     OK (GrB_Descriptor_free (&desc)) ;
103 
104     //--------------------------------------------------------------------------
105     // export the output matrix V back to MATLAB
106     //--------------------------------------------------------------------------
107 
108     pargout [0] = gb_export (&V, kind) ;
109     pargout [1] = mxCreateDoubleScalar (kind) ;
110     GB_WRAPUP ;
111 }
112 
113