1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
//------------------------------------------------------------------------------
// LAGraph_Matrix_IsEqual: check two matrices for exact equality
//------------------------------------------------------------------------------
// LAGraph, (c) 2019-2023 by The LAGraph Contributors, All Rights Reserved.
// SPDX-License-Identifier: BSD-2-Clause
//
// For additional details (including references to third party source code and
// other files) see the LICENSE file or contact permission@sei.cmu.edu. See
// Contributors.txt for a full list of contributors. Created, in part, with
// funding and support from the U.S. Government (see Acknowledgments.txt file).
// DM22-0790
// Contributed by Timothy A. Davis, Texas A&M University
//------------------------------------------------------------------------------
// LAGraph_Matrix_IsEqual: check if two matrices are identically equal (same
// size, type, structure, size, and values).
// If the two matrices have any floating point type and have
// NaNs, then these functions will return false, since NaN == NaN is false.
#define LG_FREE_WORK GrB_free (&C) ;
#include "LG_internal.h"
int LAGraph_Matrix_IsEqual
(
// output:
bool *result, // true if A == B, false if A != B or error
// input:
const GrB_Matrix A,
const GrB_Matrix B,
char *msg
)
{
//--------------------------------------------------------------------------
// check inputs
//--------------------------------------------------------------------------
LG_CLEAR_MSG ;
GrB_Matrix C = NULL ;
LG_ASSERT (result != NULL, GrB_NULL_POINTER) ;
//--------------------------------------------------------------------------
// check for NULL and aliased matrices
//--------------------------------------------------------------------------
if (A == NULL || B == NULL || A == B)
{
// two NULL matrices are identical, as are two aliased matrices
(*result) = (A == B) ;
return (GrB_SUCCESS) ;
}
//--------------------------------------------------------------------------
// compare the type of A and B
//--------------------------------------------------------------------------
GrB_Type atype ;
char atype_name [LAGRAPH_MAX_NAME_LEN] ;
char btype_name [LAGRAPH_MAX_NAME_LEN] ;
LG_TRY (LAGraph_Matrix_TypeName (atype_name, A, msg)) ;
LG_TRY (LAGraph_Matrix_TypeName (btype_name, B, msg)) ;
LG_TRY (LAGraph_TypeFromName (&atype, atype_name, msg)) ;
if (!MATCHNAME (atype_name, btype_name))
{
// types differ
(*result) = false ;
return (GrB_SUCCESS) ;
}
//--------------------------------------------------------------------------
// compare the size of A and B
//--------------------------------------------------------------------------
GrB_Index nrows1, ncols1, nrows2, ncols2 ;
GRB_TRY (GrB_Matrix_nrows (&nrows1, A)) ;
GRB_TRY (GrB_Matrix_nrows (&nrows2, B)) ;
GRB_TRY (GrB_Matrix_ncols (&ncols1, A)) ;
GRB_TRY (GrB_Matrix_ncols (&ncols2, B)) ;
if (nrows1 != nrows2 || ncols1 != ncols2)
{
// dimensions differ
(*result) = false ;
return (GrB_SUCCESS) ;
}
//--------------------------------------------------------------------------
// compare the # entries in A and B
//--------------------------------------------------------------------------
GrB_Index nvals1, nvals2 ;
GRB_TRY (GrB_Matrix_nvals (&nvals1, A)) ;
GRB_TRY (GrB_Matrix_nvals (&nvals2, B)) ;
if (nvals1 != nvals2)
{
// # of entries differ
(*result) = false ;
return (GrB_SUCCESS) ;
}
//--------------------------------------------------------------------------
// get the GrB_EQ_type operator
//--------------------------------------------------------------------------
GrB_BinaryOp op = NULL ;
if (atype == GrB_BOOL ) op = GrB_EQ_BOOL ;
else if (atype == GrB_INT8 ) op = GrB_EQ_INT8 ;
else if (atype == GrB_INT16 ) op = GrB_EQ_INT16 ;
else if (atype == GrB_INT32 ) op = GrB_EQ_INT32 ;
else if (atype == GrB_INT64 ) op = GrB_EQ_INT64 ;
else if (atype == GrB_UINT8 ) op = GrB_EQ_UINT8 ;
else if (atype == GrB_UINT16) op = GrB_EQ_UINT16 ;
else if (atype == GrB_UINT32) op = GrB_EQ_UINT32 ;
else if (atype == GrB_UINT64) op = GrB_EQ_UINT64 ;
else if (atype == GrB_FP32 ) op = GrB_EQ_FP32 ;
else if (atype == GrB_FP64 ) op = GrB_EQ_FP64 ;
// else if (atype == GxB_FC32 ) op = GxB_EQ_FC32 ;
// else if (atype == GxB_FC64 ) op = GxB_EQ_FC64 ;
LG_ASSERT_MSG (op != NULL, GrB_NOT_IMPLEMENTED, "type not supported") ;
//--------------------------------------------------------------------------
// C = A .* B, where the structure of C is the intersection of A and B
//--------------------------------------------------------------------------
GRB_TRY (GrB_Matrix_new (&C, GrB_BOOL, nrows1, ncols1)) ;
GRB_TRY (GrB_eWiseMult (C, NULL, NULL, op, A, B, NULL)) ;
//--------------------------------------------------------------------------
// ensure C has the same number of entries as A and B
//--------------------------------------------------------------------------
GrB_Index nvals ;
GRB_TRY (GrB_Matrix_nvals (&nvals, C)) ;
if (nvals != nvals1)
{
// structure of A and B are different
LG_FREE_WORK ;
(*result) = false ;
return (GrB_SUCCESS) ;
}
//--------------------------------------------------------------------------
// result = and (C)
//--------------------------------------------------------------------------
GRB_TRY (GrB_reduce (result, NULL, GrB_LAND_MONOID_BOOL, C, NULL)) ;
//--------------------------------------------------------------------------
// free workspace and return result
//--------------------------------------------------------------------------
LG_FREE_WORK ;
return (GrB_SUCCESS) ;
}