File: isequal.c

package info (click to toggle)
suitesparse-graphblas 7.4.0%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 67,112 kB
  • sloc: ansic: 1,072,243; cpp: 8,081; sh: 512; makefile: 506; asm: 369; python: 125; awk: 10
file content (170 lines) | stat: -rw-r--r-- 5,804 bytes parent folder | download | duplicates (3)
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
164
165
166
167
168
169
170
//------------------------------------------------------------------------------
// isequal: check two matrices for exact equality
//------------------------------------------------------------------------------

// SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2022, All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

//------------------------------------------------------------------------------

// isequal: check if two matrices are identically equal (same size,type,
// pattern, size, and values).  Checking for the same type requires a function
// that is an extension in SuiteSparse:GraphBLAS.  For the standard API, there
// is no way to determine the type of a matrix.

// isequal_type: uses just the standard API.

// For both methods, if the two matrices are FP32 or FP64, and have NaNs, then
// these functions will return false, since NaN == NaN is false.  To check for
// NaN equality, use isequal_type with a user-defined operator f(x,y) that
// returns true if x and y are both NaN.

#include "GraphBLAS.h"
#undef GB_PUBLIC
#define GB_LIBRARY
#include "graphblas_demos.h"

// call a GraphBLAS method and return if an error occurs
#undef  OK
#define OK(method)                                          \
{                                                           \
    GrB_Info info = method ;                                \
    if (! (info == GrB_SUCCESS || info == GrB_NO_VALUE))    \
    {                                                       \
        /* error occured: free workspace and return */      \
        GrB_Matrix_free (&C) ;                              \
        return (info) ;                                     \
    }                                                       \
}

//------------------------------------------------------------------------------
// isequal_type: check two matrices, works in any GraphBLAS
//------------------------------------------------------------------------------

GB_PUBLIC
GrB_Info isequal_type       // return GrB_SUCCESS if successful
(
    bool *result,           // true if A == B, false if A != B or error
    GrB_Matrix A,
    GrB_Matrix B,
    GrB_BinaryOp op         // should be GrB_EQ_<type>, for the type of A and B
)
{

    GrB_Matrix C = NULL ;
    GrB_Index nrows1, ncols1, nrows2, ncols2, nvals, nvals1, nvals2 ;

    if (result == NULL)
    {
        // error: required parameter, result, is NULL
        return (GrB_NULL_POINTER) ;
    }
    (*result) = false ;

    // check the size of A and B
    OK (GrB_Matrix_nrows (&nrows1, A)) ;
    OK (GrB_Matrix_nrows (&nrows2, B)) ;
    if (nrows1 != nrows2)
    {
        // # of rows differ
        return (GrB_SUCCESS) ;    
    }

    OK (GrB_Matrix_ncols (&ncols1, A)) ;
    OK (GrB_Matrix_ncols (&ncols2, B)) ;
    if (ncols1 != ncols2)
    {
        // # of cols differ
        return (GrB_SUCCESS) ;
    }

    // check the # entries in A and B
    OK (GrB_Matrix_nvals (&nvals1, A)) ;
    OK (GrB_Matrix_nvals (&nvals2, B)) ;
    if (nvals1 != nvals2)
    {
        // # of entries differ
        return (GrB_SUCCESS) ;
    }

    // C = A .* B, where the pattern of C is the intersection of A and B
    OK (GrB_Matrix_new (&C, GrB_BOOL, nrows1, ncols1)) ;
    OK (GrB_Matrix_eWiseMult_BinaryOp (C, NULL, NULL, op, A, B, NULL)) ;

    // ensure C has the same number of entries as A and B
    OK (GrB_Matrix_nvals (&nvals, C)) ;
    if (nvals != nvals1)
    {
        // pattern of A and B are different
        GrB_Matrix_free (&C) ;
        return (GrB_SUCCESS) ;
    }

    // result = and (C)
    OK (GrB_Matrix_reduce_BOOL (result, NULL, GrB_LAND_MONOID_BOOL, C, NULL)) ;

    // free workspace and return result
    GrB_Matrix_free (&C) ;
    return (GrB_SUCCESS) ;
}

//------------------------------------------------------------------------------
// isequal: for SuiteSparse/GraphBLAS only; also check if types are the same
//------------------------------------------------------------------------------

#ifdef GxB_SUITESPARSE_GRAPHBLAS
// the isequal function only works with SuiteSparse:GraphBLAS

GrB_Info isequal            // return GrB_SUCCESS if successful
(
    bool *result,           // true if A == B, false if A != B or error
    GrB_Matrix A,
    GrB_Matrix B,
    GrB_BinaryOp userop     // for A and B with user-defined types.  ignored
                            // if A and B are of built-in types
)
{
    GrB_Matrix C = NULL ;
    GrB_Type atype, btype ;
    GrB_BinaryOp op ;

    if (result == NULL)
    {
        // error: required parameter, result, is NULL
        return (GrB_NULL_POINTER) ;
    }
    (*result) = false ;

    // check the type of A and B
    OK (GxB_Matrix_type (&atype, A)) ;
    OK (GxB_Matrix_type (&btype, B)) ;
    if (atype != btype)
    {
        // types differ
        return (GrB_SUCCESS) ;
    }

    // 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   ;
    else                          op = userop ; // A and B are user-defined

    // check the size, pattern, and values of A and B
    OK (isequal_type (result, A, B, op)) ;

    // return result
    return (GrB_SUCCESS) ;
}
#endif