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