1 //------------------------------------------------------------------------------
2 // isequal: check two matrices for exact equality
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 // isequal: check if two matrices are identically equal (same size,type,
11 // pattern, size, and values). Checking for the same type requires a function
12 // that is an extension in SuiteSparse:GraphBLAS. For the standard API, there
13 // is no way to determine the type of a matrix.
14
15 // isequal_type: uses just the standard API.
16
17 // For both methods, if the two matrices are FP32 or FP64, and have NaNs, then
18 // these functions will return false, since NaN == NaN is false. To check for
19 // NaN equality (like isequalwithequalnans in MATLAB), use isequal_type with a
20 // user-defined operator f(x,y) that returns true if x and y are both NaN.
21
22 #include "GraphBLAS.h"
23 #undef GB_PUBLIC
24 #define GB_LIBRARY
25 #include "graphblas_demos.h"
26
27 // call a GraphBLAS method and return if an error occurs
28 #undef OK
29 #define OK(method) \
30 { \
31 GrB_Info info = method ; \
32 if (! (info == GrB_SUCCESS || info == GrB_NO_VALUE)) \
33 { \
34 /* error occured: free workspace and return */ \
35 GrB_Matrix_free (&C) ; \
36 return (info) ; \
37 } \
38 }
39
40 //------------------------------------------------------------------------------
41 // isequal_type: check two matrices, works in any GraphBLAS
42 //------------------------------------------------------------------------------
43
44 GB_PUBLIC
isequal_type(bool * result,GrB_Matrix A,GrB_Matrix B,GrB_BinaryOp op)45 GrB_Info isequal_type // return GrB_SUCCESS if successful
46 (
47 bool *result, // true if A == B, false if A != B or error
48 GrB_Matrix A,
49 GrB_Matrix B,
50 GrB_BinaryOp op // should be GrB_EQ_<type>, for the type of A and B
51 )
52 {
53
54 GrB_Matrix C = NULL ;
55 GrB_Index nrows1, ncols1, nrows2, ncols2, nvals, nvals1, nvals2 ;
56
57 if (result == NULL)
58 {
59 // error: required parameter, result, is NULL
60 return (GrB_NULL_POINTER) ;
61 }
62 (*result) = false ;
63
64 // check the size of A and B
65 OK (GrB_Matrix_nrows (&nrows1, A)) ;
66 OK (GrB_Matrix_nrows (&nrows2, B)) ;
67 if (nrows1 != nrows2)
68 {
69 // # of rows differ
70 return (GrB_SUCCESS) ;
71 }
72
73 OK (GrB_Matrix_ncols (&ncols1, A)) ;
74 OK (GrB_Matrix_ncols (&ncols2, B)) ;
75 if (ncols1 != ncols2)
76 {
77 // # of cols differ
78 return (GrB_SUCCESS) ;
79 }
80
81 // check the # entries in A and B
82 OK (GrB_Matrix_nvals (&nvals1, A)) ;
83 OK (GrB_Matrix_nvals (&nvals2, B)) ;
84 if (nvals1 != nvals2)
85 {
86 // # of entries differ
87 return (GrB_SUCCESS) ;
88 }
89
90 // C = A .* B, where the pattern of C is the intersection of A and B
91 OK (GrB_Matrix_new (&C, GrB_BOOL, nrows1, ncols1)) ;
92 OK (GrB_Matrix_eWiseMult_BinaryOp (C, NULL, NULL, op, A, B, NULL)) ;
93
94 // ensure C has the same number of entries as A and B
95 OK (GrB_Matrix_nvals (&nvals, C)) ;
96 if (nvals != nvals1)
97 {
98 // pattern of A and B are different
99 GrB_Matrix_free (&C) ;
100 return (GrB_SUCCESS) ;
101 }
102
103 // result = and (C)
104 OK (GrB_Matrix_reduce_BOOL (result, NULL, GrB_LAND_MONOID_BOOL, C, NULL)) ;
105
106 // free workspace and return result
107 GrB_Matrix_free (&C) ;
108 return (GrB_SUCCESS) ;
109 }
110
111 //------------------------------------------------------------------------------
112 // isequal: for SuiteSparse/GraphBLAS only; also check if types are the same
113 //------------------------------------------------------------------------------
114
115 #ifdef GxB_SUITESPARSE_GRAPHBLAS
116 // the isequal function only works with SuiteSparse:GraphBLAS
117
isequal(bool * result,GrB_Matrix A,GrB_Matrix B,GrB_BinaryOp userop)118 GrB_Info isequal // return GrB_SUCCESS if successful
119 (
120 bool *result, // true if A == B, false if A != B or error
121 GrB_Matrix A,
122 GrB_Matrix B,
123 GrB_BinaryOp userop // for A and B with user-defined types. ignored
124 // if A and B are of built-in types
125 )
126 {
127 GrB_Matrix C = NULL ;
128 GrB_Type atype, btype ;
129 GrB_BinaryOp op ;
130
131 if (result == NULL)
132 {
133 // error: required parameter, result, is NULL
134 return (GrB_NULL_POINTER) ;
135 }
136 (*result) = false ;
137
138 // check the type of A and B
139 OK (GxB_Matrix_type (&atype, A)) ;
140 OK (GxB_Matrix_type (&btype, B)) ;
141 if (atype != btype)
142 {
143 // types differ
144 return (GrB_SUCCESS) ;
145 }
146
147 // select the comparator operator
148 if (atype == GrB_BOOL ) op = GrB_EQ_BOOL ;
149 else if (atype == GrB_INT8 ) op = GrB_EQ_INT8 ;
150 else if (atype == GrB_INT16 ) op = GrB_EQ_INT16 ;
151 else if (atype == GrB_INT32 ) op = GrB_EQ_INT32 ;
152 else if (atype == GrB_INT64 ) op = GrB_EQ_INT64 ;
153 else if (atype == GrB_UINT8 ) op = GrB_EQ_UINT8 ;
154 else if (atype == GrB_UINT16) op = GrB_EQ_UINT16 ;
155 else if (atype == GrB_UINT32) op = GrB_EQ_UINT32 ;
156 else if (atype == GrB_UINT64) op = GrB_EQ_UINT64 ;
157 else if (atype == GrB_FP32 ) op = GrB_EQ_FP32 ;
158 else if (atype == GrB_FP64 ) op = GrB_EQ_FP64 ;
159 else if (atype == GxB_FC32 ) op = GxB_EQ_FC32 ;
160 else if (atype == GxB_FC64 ) op = GxB_EQ_FC64 ;
161 else op = userop ; // A and B are user-defined
162
163 // check the size, pattern, and values of A and B
164 OK (isequal_type (result, A, B, op)) ;
165
166 // return result
167 return (GrB_SUCCESS) ;
168 }
169 #endif
170
171