File: GB_iso_check.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 (143 lines) | stat: -rw-r--r-- 5,289 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
//------------------------------------------------------------------------------
// GB_iso_check: check if all entries in a matrix are identical
//------------------------------------------------------------------------------

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

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

// Returns true if all entries in A are the same, and A can then be converted
// to iso if currently non-iso.  Returns false if A is bitmap, has any zombies,
// or has or pending tuples, since these are more costly to check.

#include "GB_atomics.h"

bool GB_iso_check               // return true if A is iso, false otherwise
(
    const GrB_Matrix A,         // matrix to reduce
    GB_Context Context
)
{

    //--------------------------------------------------------------------------
    // check inputs
    //--------------------------------------------------------------------------

    if (A == NULL || GB_nnz (A) == 0 || GB_nnz_held (A) == 0)
    { 
        // empty matrices cannot be iso
        return (false) ;
    }
    else if (A->iso)
    { 
        // nothing to do; A is already iso
        return (true) ;
    }
    else if (GB_PENDING (A) || GB_ZOMBIES (A) || GB_IS_BITMAP (A))
    { 
        // Non-iso matrices with pending work are assumed to be non-iso.
        // Bitmap matrices and matrices with zombies could be checked, but
        // finding the first entry is tedious so this is skipped.  Matrices
        // with pending work could be finished first, but this is costly so it
        // is skipped.
        return (false) ;
    }

    ASSERT (!GB_ZOMBIES (A)) ;
    ASSERT (GB_JUMBLED_OK (A)) ;
    ASSERT (!GB_PENDING (A)) ;
    ASSERT (!GB_IS_BITMAP (A)) ;
    ASSERT_MATRIX_OK (A, "A input for GB_iso_check", GB0) ;

    //--------------------------------------------------------------------------
    // get A
    //--------------------------------------------------------------------------

    int64_t asize = A->type->size ;
    int64_t anz = GB_nnz_held (A) ;
    bool iso = true ;       // A is iso until proven otherwise

    //--------------------------------------------------------------------------
    // determine the number of threads to use
    //--------------------------------------------------------------------------

    int nthreads = 0, ntasks = 0 ;
    GB_GET_NTHREADS_MAX (nthreads_max, chunk, Context) ;
    nthreads = GB_nthreads (anz, chunk, nthreads_max) ;
    ntasks = (nthreads == 1) ? 1 : (64 * nthreads) ;
    ntasks = GB_IMIN (ntasks, anz) ;
    ntasks = GB_IMAX (ntasks, 1) ;

    //--------------------------------------------------------------------------
    // check if A is iso
    //--------------------------------------------------------------------------

    bool done = false ;

    #ifndef GBCUDA_DEV
    {

        #define GB_GET_FIRST_VALUE(atype_t, a, Ax)                      \
            const atype_t a = Ax [0]
        #define GB_COMPARE_WITH_FIRST_VALUE(my_iso, a, Ax, p)           \
            my_iso = my_iso & (a == Ax [p])

        switch (asize)
        {
            case GB_1BYTE : // uint8, int8, bool, or 1-byte user
                #define GB_ATYPE uint8_t
                #include "GB_iso_check_template.c"
                break ;

            case GB_2BYTE : // uint16, int16, or 2-byte user
                #define GB_ATYPE uint16_t
                #include "GB_iso_check_template.c"
                break ;

            case GB_4BYTE : // uint32, int32, float, or 4-byte user
                #define GB_ATYPE uint32_t
                #include "GB_iso_check_template.c"
                break ;

            case GB_8BYTE : // uint64, int64, double, float complex,
                            // or 8-byte user defined
                #define GB_ATYPE uint64_t
                #include "GB_iso_check_template.c"
                break ;

            case GB_16BYTE : // double complex or 16-byte user
                #define GB_ATYPE uint64_t
                #undef  GB_GET_FIRST_VALUE
                #define GB_GET_FIRST_VALUE(atype_t, a, Ax)              \
                    const atype_t a ## 0 = Ax [0] ;                     \
                    const atype_t a ## 1 = Ax [1] ;
                #undef  GB_COMPARE_WITH_FIRST_VALUE
                #define GB_COMPARE_WITH_FIRST_VALUE(my_iso, a, Ax, p)   \
                    my_iso = my_iso & (a ## 0 == Ax [2*p  ])            \
                                    & (a ## 1 == Ax [2*p+1])
                #include "GB_iso_check_template.c"
                break ;

            default:;
        }
    }
    #endif

    if (!done)
    { 
        // with user-defined types of any size
        #define GB_ATYPE GB_void
        #undef  GB_GET_FIRST_VALUE
        #define GB_GET_FIRST_VALUE(atype_t, a, Ax)                      \
            GB_void a [GB_VLA(asize)] ;                                 \
            memcpy (a, Ax, asize) ;
        #undef  GB_COMPARE_WITH_FIRST_VALUE
        #define GB_COMPARE_WITH_FIRST_VALUE(my_iso, a, Ax, p)           \
            my_iso = my_iso & (memcmp (a, Ax + (p)*asize, asize) == 0)
        #include "GB_iso_check_template.c"
    }

    return (iso) ;
}