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
160
161
162
163
//------------------------------------------------------------------------------
// LAGraph_Vector_IsEqual: check two vectors for exact equality
//------------------------------------------------------------------------------
// LAGraph, (c) 2019-2022 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_Vector_IsEqual: checks if two vectors are identically equal (same
// size, type, structure, size, and values).
// See also LAGraph_Matrix_IsEqual.
// If the two vectors are GrB_FP32, GrB_FP64, or related, and have NaNs, then
// this function will return false, since NaN == NaN is false. To check for
// NaN equality (like isequalwithequalnans in MATLAB), use
// LAGraph_Vector_IsEqualOp with a user-defined operator f(x,y) that returns
// true if x and y are both NaN.
#define LG_FREE_WORK GrB_free (&C) ;
#include "LG_internal.h"
int LAGraph_Vector_IsEqual
(
// output:
bool *result, // true if A == B, false if A != B or error
// input:
const GrB_Vector A,
const GrB_Vector B,
char *msg
)
{
//--------------------------------------------------------------------------
// check inputs
//--------------------------------------------------------------------------
LG_CLEAR_MSG ;
GrB_Vector C = NULL ;
LG_ASSERT (result != NULL, GrB_NULL_POINTER) ;
//--------------------------------------------------------------------------
// check for NULL and aliased vectors
//--------------------------------------------------------------------------
if (A == NULL || B == NULL || A == B)
{
// two NULL vectors 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_Vector_TypeName (atype_name, A, msg)) ;
LG_TRY (LAGraph_Vector_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, nrows2;
GRB_TRY (GrB_Vector_size (&nrows1, A)) ;
GRB_TRY (GrB_Vector_size (&nrows2, B)) ;
if (nrows1 != nrows2)
{
// # of rows differ
(*result) = false ;
return (GrB_SUCCESS) ;
}
//--------------------------------------------------------------------------
// compare the # entries in A and B
//--------------------------------------------------------------------------
GrB_Index nvals1, nvals2 ;
GRB_TRY (GrB_Vector_nvals (&nvals1, A)) ;
GRB_TRY (GrB_Vector_nvals (&nvals2, B)) ;
if (nvals1 != nvals2)
{
// # of entries differ
(*result) = false ;
return (GrB_SUCCESS) ;
}
//--------------------------------------------------------------------------
// get the GrB_EQ_type operator
//--------------------------------------------------------------------------
GrB_BinaryOp op = NULL ;
// select the comparator operator
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_Vector_new (&C, GrB_BOOL, nrows1)) ;
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_Vector_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) ;
}