1 //------------------------------------------------------------------------------
2 // GB_mx_isequal: check if two matrices are equal
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 #include "GB_mex.h"
11
GB_mx_isequal(GrB_Matrix A,GrB_Matrix B,double eps)12 bool GB_mx_isequal // true if A and B are exactly the same
13 (
14 GrB_Matrix A,
15 GrB_Matrix B,
16 double eps // if A and B are both FP32 or FP64, and if eps > 0,
17 // then the values are considered equal if their relative
18 // difference is less than or equal to eps.
19 )
20 {
21
22 if (A == B) return (true) ;
23 if (A == NULL) return (false) ;
24 if (B == NULL) return (false) ;
25
26 int A_sparsity = GB_sparsity (A) ;
27 if (A_sparsity != GB_sparsity (B))
28 {
29 return (false) ;
30 }
31
32 GB_Pending AP = A->Pending ;
33 GB_Pending BP = B->Pending ;
34
35 if (A->magic != B->magic) return (false) ;
36 if (A->type != B->type ) return (false) ;
37 if (A->vlen != B->vlen ) return (false) ;
38 if (A->vdim != B->vdim ) return (false) ;
39 if (A->nvec != B->nvec ) return (false) ;
40
41 if (GB_NNZ (A) != GB_NNZ (B) ) return (false) ;
42
43 if ((A->h != NULL) != (B->h != NULL)) return (false) ;
44 if (A->is_csc != B->is_csc ) return (false) ;
45
46 // these differences are OK
47 // if (A->plen != B->plen ) return (false) ;
48 // if (A->nzmax != B->nzmax) return (false) ;
49 // if (AP->nmax != BP->nmax) return (false) ;
50
51 // if (A->p_shallow != B->p_shallow ) return (false) ;
52 // if (A->h_shallow != B->h_shallow ) return (false) ;
53 // if (A->i_shallow != B->i_shallow ) return (false) ;
54 // if (A->x_shallow != B->i_shallow ) return (false) ;
55
56 if (A->nzombies != B->nzombies ) return (false) ;
57
58 if ((AP != NULL) != (BP != NULL)) return (false) ;
59
60 if (AP != NULL)
61 {
62 if (AP->n != BP->n ) return (false) ;
63 if (AP->sorted != BP->sorted) return (false) ;
64 if (AP->op != BP->op ) return (false) ;
65 if (AP->type != BP->type ) return (false) ;
66 if (AP->size != BP->size ) return (false) ;
67 }
68
69 int64_t n = A->nvec ;
70 int64_t nnz = GB_NNZ (A) ;
71 size_t s = sizeof (int64_t) ;
72 size_t asize = A->type->size ;
73
74 ASSERT (n >= 0 && n <= A->vdim) ;
75
76 bool A_is_dense = GB_is_dense (A) || GB_IS_FULL (A) ;
77 bool B_is_dense = GB_is_dense (B) || GB_IS_FULL (B) ;
78
79 if (A_is_dense != B_is_dense) return (false) ;
80
81 if (!A_is_dense)
82 {
83 if (!GB_mx_same ((char *) A->p, (char *) B->p, (n+1) * s))
84 {
85 return (false) ;
86 }
87 if (A->h != NULL)
88 {
89 if (!GB_mx_same ((char *) A->h, (char *) B->h, n * s))
90 return (false) ;
91 }
92 }
93
94 if (A_sparsity == GxB_BITMAP)
95 {
96 if (!GB_mx_same ((char *) A->b, (char *) B->b, nnz))
97 {
98 return (false) ;
99 }
100 }
101
102 if (A->nzmax > 0 && B->nzmax > 0)
103 {
104 if (!A_is_dense)
105 {
106 if (!GB_mx_same ((char *) A->i, (char *) B->i, nnz * s))
107 {
108 return (false) ;
109 }
110 }
111
112 if (A->type == GrB_FP32 && eps > 0)
113 {
114 if (!GB_mx_xsame32 (A->x, B->x, A->b, nnz, A->i, eps))
115 return (false) ;
116 }
117 else if (A->type == GrB_FP64 && eps > 0)
118 {
119 if (!GB_mx_xsame64 (A->x, B->x, A->b, nnz, A->i, eps))
120 return (false) ;
121 }
122 else
123 {
124 if (!GB_mx_xsame (A->x, B->x, A->b, nnz, asize, A->i))
125 return (false) ;
126 }
127 }
128
129 if (AP != NULL)
130 {
131 size_t psize = AP->size ;
132 int64_t np = AP->n ;
133 if (!GB_mx_same ((char *) AP->i, (char *) BP->i, np*s)) return (false) ;
134 if (!GB_mx_same ((char *) AP->j, (char *) BP->j, np*s)) return (false) ;
135 if (!GB_mx_same ((char *) AP->x, (char *) BP->x, np*psize))
136 {
137 return (false) ;
138 }
139 }
140
141 return (true) ;
142 }
143
144