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) ;
}
|