1 //------------------------------------------------------------------------------
2 // GB_matvec_build: check inputs and build a matrix or vector
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 // CALLED BY: GrB_Matrix_build_* and GrB_Vector_build_*
11 // CALLS: GB_build
12
13 // This function implements GrB_Matrix_build_* and GrB_Vector_build_*. It
14 // first constructs T by GB_builder as hypersparse, and GB_build conforms the
15 // result to the appropriate sparsity structure of C.
16
17 #include "GB_build.h"
18
GB_matvec_build(GrB_Matrix C,const GrB_Index * I,const GrB_Index * J,const void * X,const GrB_Index nvals,const GrB_BinaryOp dup,const GB_Type_code scode,const bool is_matrix,GB_Context Context)19 GrB_Info GB_matvec_build // check inputs then build matrix or vector
20 (
21 GrB_Matrix C, // matrix or vector to build
22 const GrB_Index *I, // row indices of tuples
23 const GrB_Index *J, // col indices of tuples (NULL for vector)
24 const void *X, // array of values of tuples
25 const GrB_Index nvals, // number of tuples
26 const GrB_BinaryOp dup, // binary function to assemble duplicates
27 const GB_Type_code scode, // GB_Type_code of X array
28 const bool is_matrix, // true if C is a matrix, false if GrB_Vector
29 GB_Context Context
30 )
31 {
32
33 //--------------------------------------------------------------------------
34 // check inputs
35 //--------------------------------------------------------------------------
36
37 ASSERT_MATRIX_OK (C, "C for GB_matvec_build", GB0) ;
38
39 GB_RETURN_IF_NULL (I) ;
40 if (I == GrB_ALL)
41 {
42 GB_ERROR (GrB_INVALID_VALUE, "List of row indices cannot be %s",
43 "GrB_ALL") ;
44 }
45
46 if (nvals == GxB_RANGE || nvals == GxB_STRIDE || nvals == GxB_BACKWARDS)
47 {
48 GB_ERROR (GrB_INVALID_VALUE, "nvals cannot be %s",
49 "GxB_RANGE, GxB_STRIDE, or GxB_BACKWARDS") ;
50 }
51
52 if (is_matrix)
53 {
54 GB_RETURN_IF_NULL (J) ;
55 if (J == GrB_ALL)
56 {
57 GB_ERROR (GrB_INVALID_VALUE, "List of column indices cannot be %s",
58 "GrB_ALL") ;
59 }
60 }
61 else
62 {
63 // only GrB_Vector_build calls this function with J == NULL
64 ASSERT (J == NULL) ;
65 }
66
67 GB_RETURN_IF_NULL (X) ;
68 GB_RETURN_IF_NULL_OR_FAULTY (dup) ;
69 if (GB_OP_IS_POSITIONAL (dup))
70 {
71 // dup operator cannot be a positional op
72 GB_ERROR (GrB_DOMAIN_MISMATCH,
73 "Positional op z=%s(x,y) not supported as dup op\n", dup->name) ;
74 }
75
76 ASSERT_BINARYOP_OK (dup, "dup operator for assembling duplicates", GB0) ;
77 ASSERT (scode <= GB_UDT_code) ;
78
79 if (nvals > GxB_INDEX_MAX)
80 {
81 // problem too large
82 GB_ERROR (GrB_INVALID_VALUE,
83 "Problem too large: nvals " GBu " exceeds " GBu,
84 nvals, GxB_INDEX_MAX) ;
85 }
86
87 // check types of dup
88 if (dup->xtype != dup->ztype || dup->ytype != dup->ztype)
89 {
90 // all 3 types of z = dup (x,y) must be the same. dup must also be
91 // associative but there is no way to check this in general.
92 GB_ERROR (GrB_DOMAIN_MISMATCH, "All domains of dup "
93 "operator for assembling duplicates must be identical.\n"
94 "operator is: [%s] = %s ([%s],[%s])",
95 dup->ztype->name, dup->name, dup->xtype->name, dup->ytype->name) ;
96 }
97
98 if (!GB_Type_compatible (C->type, dup->ztype))
99 {
100 // the type of C and dup must be compatible
101 GB_ERROR (GrB_DOMAIN_MISMATCH,
102 "Operator [%s] for assembling duplicates has type [%s],\n"
103 "cannot be typecast to entries in output of type [%s]",
104 dup->name, dup->ztype->name, C->type->name) ;
105 }
106
107 // C and X must be compatible
108 if (!GB_code_compatible (scode, dup->ztype->code))
109 {
110 // All types must be compatible with each other: C, dup, and X.
111 // User-defined types are only compatible with themselves; they are not
112 // compatible with any built-in type nor any other user-defined type.
113 // Thus, if C, dup, or X have any user-defined type, this
114 // condition requires all three types to be identical: the same
115 // user-defined type. No casting will be done in this case.
116 GB_ERROR (GrB_DOMAIN_MISMATCH,
117 "Numerical values of tuples of type [%s]\n"
118 "cannot be typecast as input to the dup operator\n"
119 "z=%s(x,y), whose input types are [%s]",
120 GB_code_string (scode), dup->name, dup->ztype->name) ;
121 }
122
123 if (!GB_IS_EMPTY (C))
124 {
125 // The matrix has existing entries. This is required by the GraphBLAS
126 // API specification to generate an error, so the test is made here.
127 // However, any existing content is safely freed immediately below, so
128 // this test is not required, except to conform to the spec. Zombies
129 // are excluded from this test.
130 GB_ERROR (GrB_OUTPUT_NOT_EMPTY,
131 "Output already has %s", "existing entries") ;
132 }
133
134 //--------------------------------------------------------------------------
135 // build the matrix
136 //--------------------------------------------------------------------------
137
138 // GB_build treats I, J, and X as read-only; they must not be modified
139
140 return (GB_build (C, I, J, X, nvals, dup, scode, is_matrix,
141 /* true, */ Context)) ;
142 }
143
144