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 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
|
//------------------------------------------------------------------------------
// GxB_Matrix_Iterator: seek to a specific entry for a matrix iterator
//------------------------------------------------------------------------------
// SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2022, All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
#include "GB.h"
#include "GB_search_for_vector_template.c"
//------------------------------------------------------------------------------
// GxB_Matrix_Iterator_attach: attach an entry iterator to a matrix
//------------------------------------------------------------------------------
// On input, the iterator must already exist, having been created by
// GxB_Iterator_new.
// GxB_Matrix_Iterator_attach attaches an entry iterator to a matrix. If the
// iterator is already attached to a matrix, it is detached and then attached
// to the given matrix A.
// The following error conditions are returned:
// GrB_NULL_POINTER: if the iterator or A are NULL.
// GrB_INVALID_OBJECT: if the matrix A is invalid.
// GrB_OUT_OF_MEMORY: if the method runs out of memory.
// If successful, the entry iterator is attached to the matrix, but not to any
// specific entry. Use GxB_Matrix_Iterator_*seek* to move the iterator to a
// particular entry.
GrB_Info GxB_Matrix_Iterator_attach
(
GxB_Iterator iterator,
GrB_Matrix A,
GrB_Descriptor desc
)
{
return (GB_Iterator_attach (iterator, A, GxB_NO_FORMAT, desc)) ;
}
//------------------------------------------------------------------------------
// GxB_Matrix_Iterator_getpmax: return the range of the iterator
//------------------------------------------------------------------------------
// On input, the entry iterator must be already attached to a matrix via
// GxB_Matrix_Iterator_attach; results are undefined if this condition is not
// met.
// Entries in a matrix are given an index p, ranging from 0 to pmax-1, where
// pmax >= nvals(A). For sparse, hypersparse, and full matrices, pmax is equal
// to nvals(A). For an m-by-n bitmap matrix, pmax=m*n, or pmax=0 if the
// matrix has no entries.
GrB_Index GxB_Matrix_Iterator_getpmax (GxB_Iterator iterator)
{
return (iterator->pmax) ;
}
//------------------------------------------------------------------------------
// GB_full_position: find the vector containing p for a full/bitmap matrix
//------------------------------------------------------------------------------
static inline GrB_Info GB_full_position (GxB_Iterator iterator)
{
iterator->k = iterator->p / iterator->avlen ;
iterator->pstart = iterator->k * iterator->avlen ;
iterator->pend = iterator->pstart + iterator->avlen ;
return (GrB_SUCCESS) ;
}
//------------------------------------------------------------------------------
// GB_check_for_end_of_vector: move to next vector if current vector is done
//------------------------------------------------------------------------------
static inline GrB_Info GB_check_for_end_of_vector (GxB_Iterator iterator)
{
// move to the next vector if p has reached the end of the current vector
switch (iterator->A_sparsity)
{
default:
case GxB_SPARSE :
case GxB_HYPERSPARSE :
{
if (iterator->p >= iterator->pend)
{
// the kth vector is done; move to the next non-empty vector
iterator->pstart = iterator->pend ;
iterator->k++ ;
while (iterator->Ap [iterator->k+1] == iterator->pend)
{
// iterator->k is an empty vector; move to the next one
iterator->k++ ;
ASSERT (iterator->k < iterator->anvec) ;
}
// iterator->k is now the next non-empty vector
iterator->pend = iterator->Ap [iterator->k+1] ;
return (GrB_SUCCESS) ;
}
}
break ;
case GxB_BITMAP :
{
for ( ; iterator->p < iterator->pmax ; iterator->p++)
{
if (iterator->Ab [iterator->p])
{
// found the next entry; check if it is past the kth vector
if (iterator->p >= iterator->pend)
{
// find the vector of this entry
return (GB_full_position (iterator)) ;
}
return (GrB_SUCCESS) ;
}
}
return (GxB_EXHAUSTED) ;
}
break ;
case GxB_FULL :
{
if (iterator->p >= iterator->pend)
{
// kth vector is done; move to the next vector
iterator->k++ ;
iterator->pstart += iterator->avlen ;
iterator->pend += iterator->avlen ;
}
}
break ;
}
return (GrB_SUCCESS) ;
}
//------------------------------------------------------------------------------
// GxB_Matrix_Iterator_next: move an entry iterator to the next entry
//------------------------------------------------------------------------------
GrB_Info GxB_Matrix_Iterator_next (GxB_Iterator iterator)
{
// move to the next entry
if (++(iterator->p) >= iterator->pmax)
{
// the iterator is exhausted
iterator->p = iterator->pmax ;
return (GxB_EXHAUSTED) ;
}
else
{
// move to next vector if iterator has reached the end of a vector
return (GB_check_for_end_of_vector (iterator)) ;
}
}
//------------------------------------------------------------------------------
// GxB_Matrix_Iterator_seek: seek an entry iterator to any entry
//------------------------------------------------------------------------------
GrB_Info GxB_Matrix_Iterator_seek
(
GxB_Iterator iterator,
GrB_Index p
)
{
if (p >= iterator->pmax)
{
// the iterator is exhausted
iterator->p = iterator->pmax ;
return (GxB_EXHAUSTED) ;
}
else if (p == 0)
{
// seek to the first entry of the first vector A(:,0)
iterator->pstart = 0 ;
iterator->pend = (iterator->Ap != NULL) ?
iterator->Ap [1] : iterator->avlen ;
iterator->p = 0 ;
iterator->k = 0 ;
// move to the next non-empty vector if A(:,0) is empty
return (GB_check_for_end_of_vector (iterator)) ;
}
else
{
// seek to an arbitrary position in the matrix
iterator->p = p ;
switch (iterator->A_sparsity)
{
default:
case GxB_SPARSE :
case GxB_HYPERSPARSE :
{
// find the vector k that contains position p
iterator->k = GB_search_for_vector (p, iterator->Ap,
0, iterator->anvec, iterator->avlen) ;
iterator->pstart = iterator->Ap [iterator->k] ;
iterator->pend = iterator->Ap [iterator->k+1] ;
}
break ;
case GxB_BITMAP :
{
for ( ; iterator->p < iterator->pmax ; iterator->p++)
{
if (iterator->Ab [iterator->p])
{
// found next entry; find the vector that contains it
return (GB_full_position (iterator)) ;
}
}
return (GxB_EXHAUSTED) ;
}
break ;
case GxB_FULL :
{
// find the vector k that contains position p
return (GB_full_position (iterator)) ;
}
break ;
}
}
return (GrB_SUCCESS) ;
}
//------------------------------------------------------------------------------
// GxB_Matrix_Iterator_getp: get the current position of a matrix iterator
//------------------------------------------------------------------------------
// On input, the entry iterator must be already attached to a matrix via
// GxB_Matrix_Iterator_attach, and the position of the iterator must also have
// been defined by a prior call to GxB_Matrix_Iterator_seek or
// GxB_Matrix_Iterator_next. Results are undefined if these conditions are not
// met.
GrB_Index GxB_Matrix_Iterator_getp (GxB_Iterator iterator)
{
return (iterator->p) ;
}
//------------------------------------------------------------------------------
// GxB_Matrix_Iterator_getIndex: get the row and column index of a matrix entry
//------------------------------------------------------------------------------
// On input, the entry iterator must be already attached to a matrix via
// GxB_Matrix_Iterator_attach, and the position of the iterator must also have
// been defined by a prior call to GxB_Matrix_Iterator_seek or
// GxB_Matrix_Iterator_next, with a return value of GrB_SUCCESS. Results are
// undefined if these conditions are not met.
void GxB_Matrix_Iterator_getIndex
(
GxB_Iterator iterator,
GrB_Index *row,
GrB_Index *col
)
{
// get row and column index of current entry, for matrix iterator
switch (iterator->A_sparsity)
{
default:
case GxB_SPARSE :
{
if (iterator->by_col)
{
(*row) = iterator->Ai [iterator->p] ;
(*col) = iterator->k ;
}
else
{
(*row) = iterator->k ;
(*col) = iterator->Ai [iterator->p] ;
}
}
break ;
case GxB_HYPERSPARSE :
{
if (iterator->by_col)
{
(*row) = iterator->Ai [iterator->p] ;
(*col) = iterator->Ah [iterator->k] ;
}
else
{
(*row) = iterator->Ah [iterator->k] ;
(*col) = iterator->Ai [iterator->p] ;
}
}
break ;
case GxB_BITMAP :
case GxB_FULL :
{
if (iterator->by_col)
{
(*row) = iterator->p - iterator->pstart ;
(*col) = iterator->k ;
}
else
{
(*row) = iterator->k ;
(*col) = iterator->p - iterator->pstart ;
}
}
break ;
}
}
|