1function ok = GB_spec_compare (C_spec, C_mex, identity, tol)
2%GB_SPEC_COMPARE compare MATLAB mimic result with GraphBLAS result
3% ok = GB_spec_compare (C_spec, C_mex, identity, tol)
4%
5% compares two structs C_spec and C_mex.  The C_spec struct contains a dense
6% matrix and is the output of a MATLAB mimic, C_spec = GB_spec_* (...) for
7% some GraphBLAS method.  C_mex = GB_mex_* (...) is the output of the
8% corresponding MATLAB interface to the true GraphBLAS method, in C.
9
10% SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
11% SPDX-License-Identifier: Apache-2.0
12
13% get the semiring identity
14if (nargin < 3)
15    identity = 0 ;
16end
17if (isempty (identity))
18    % results from the ANY monoid or operator cannot be checked with
19    % this function, since many results are possible.
20    ok = true ;
21    return
22end
23
24if (nargin < 4)
25    if (isfloat (identity))
26        tol = 64*eps (class (identity)) ;   % not GB_spec_type.
27    else
28        tol = 0 ;
29    end
30end
31
32% Convert C_mex from a sparse matrix into a dense matrix.  It will have
33% explicit identity values where entries were not in the pattern of the sparse
34% C_mex.matrix.  Entries outside the pattern are "don't care" values.  They may
35% differ between C_spec and C_mex, because the latter works on dense matrices
36% and thus must compute the entries.  With typecasting, an identity value may
37% get modified.  C_mex, on the other hand, is computed in a GraphBLAS sparse
38% matrix, and never appears.  It is only converted here to a dense matrix, with
39% the implicit entries being replaced with identity.  C_spec is also converted,
40% using the same identity value.
41C1 = GB_spec_matrix (C_spec, identity) ;
42C2 = GB_spec_matrix (C_mex, identity) ;
43
44try
45    % ok_matrix = isequalwithequalnans (C1.matrix, C2.matrix) ;
46    ok_matrix = isequal_roundoff (C1.matrix, C2.matrix, tol) ;
47catch
48    ok_matrix = false ;
49end
50
51try
52    ok_pattern = isequal (C1.pattern, C2.pattern) ;
53catch
54    ok_pattern = false ;
55end
56
57try
58    ok_class = isequal (C1.class, C2.class) ;
59catch
60    ok_class = false ;
61end
62
63%{
64if (~ok_class)
65    fprintf ('class is wrong:\n') ;
66    % C1.class
67    % C2.class
68end
69
70if (~ok_matrix)
71    fprintf ('matrix is wrong:\n') ;
72    identity
73    % C1.matrix
74    % C2.matrix
75end
76if (~ok_pattern)
77    fprintf ('pattern is wrong:\n') ;
78    C1.pattern
79    C2.pattern
80end
81%}
82
83if (~ok_class || ~ok_pattern || ~ok_matrix)
84    fprintf ('matrix: %d pattern: %d class %d\n', ...
85        ok_matrix, ok_pattern, ok_class) ;
86    norm (double (C1.matrix) - double (C2.matrix), 1)
87end
88
89% with no output, just assert that ok is true
90if (nargout == 0)
91    assert (ok_matrix && ok_pattern && ok_class) ;
92end
93
94