Skip to content

Commit 8d9eb2c

Browse files
committed
Add apply_IndexOp_Scalar to matrix and vector functional API
Add matrix_apply_indexop and vector_apply_indexop wrapping the GrB_Matrix_apply_IndexOp_Scalar and GrB_Vector_apply_IndexOp_Scalar C functions, with doctests. Update BFS example to use the new vector_apply_indexop instead of raw ffi calls.
1 parent 6b59417 commit 8d9eb2c

3 files changed

Lines changed: 61 additions & 7 deletions

File tree

suitesparse_graphblas/api/examples/bfs.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
[0, 0, 1, 2]
3030
"""
3131

32-
from suitesparse_graphblas import check_status, ffi, lib
32+
from suitesparse_graphblas import lib
3333
from suitesparse_graphblas.api import matrix, scalar, vector
3434

3535

@@ -69,6 +69,8 @@ def bfs(A, src, compute_level=True, compute_parent=True):
6969
semiring = lib.GrB_MIN_FIRST_SEMIRING_INT64
7070
frontier = vector.vector_new(lib.GrB_INT64, n)
7171
vector.set_int64(frontier, src, src)
72+
index_thunk = scalar.scalar_new(lib.GrB_INT64)
73+
scalar.set_int64(index_thunk, 0)
7274
else:
7375
# Level-only mode: frontier is BOOL.
7476
# Semiring: ANY_PAIR just checks reachability.
@@ -106,12 +108,8 @@ def bfs(A, src, compute_level=True, compute_parent=True):
106108
# Convert frontier values to their own indices (ROWINDEX).
107109
# After this, frontier(i) == i for every stored entry,
108110
# so the next vxm propagates node i as the parent ID.
109-
check_status(
110-
frontier,
111-
lib.GrB_Vector_apply_IndexOp_INT64(
112-
frontier[0], ffi.NULL, ffi.NULL,
113-
lib.GrB_ROWINDEX_INT64, frontier[0], 0, ffi.NULL,
114-
),
111+
vector.vector_apply_indexop(
112+
frontier, lib.GrB_ROWINDEX_INT64, frontier, index_thunk,
115113
)
116114

117115
current_level += 1

suitesparse_graphblas/api/matrix.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,34 @@ def matrix_apply_second(C, op, A, y, mask=None, accum=None, desc=None):
505505
))
506506

507507

508+
def matrix_apply_indexop(C, op, A, thunk, mask=None, accum=None, desc=None):
509+
"""Apply an index unary operator to each entry of a matrix with a scalar thunk.
510+
511+
>>> from suitesparse_graphblas import scalar
512+
>>> C = matrix_new(lib.GrB_INT64, 3, 3)
513+
>>> A = matrix_new(lib.GrB_INT64, 3, 3)
514+
>>> set_int64(A, 10, 0, 0)
515+
>>> set_int64(A, 20, 1, 1)
516+
>>> s = scalar.scalar_new(lib.GrB_INT64)
517+
>>> scalar.set_int64(s, 0)
518+
>>> matrix_apply_indexop(C, lib.GrB_ROWINDEX_INT64, A, s)
519+
>>> get_int64(C, 0, 0) == 0
520+
True
521+
>>> get_int64(C, 1, 1) == 1
522+
True
523+
524+
"""
525+
check_status(C, lib.GrB_Matrix_apply_IndexOp_Scalar(
526+
C[0],
527+
ffi.NULL if mask is None else mask[0],
528+
ffi.NULL if accum is None else accum,
529+
op,
530+
A[0],
531+
thunk[0],
532+
ffi.NULL if desc is None else desc,
533+
))
534+
535+
508536
def matrix_select(C, op, A, thunk, mask=None, accum=None, desc=None):
509537
"""Select entries from a matrix using an index unary operator and scalar thunk.
510538

suitesparse_graphblas/api/vector.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,34 @@ def vector_apply_second(w, op, u, y, mask=None, accum=None, desc=None):
432432
))
433433

434434

435+
def vector_apply_indexop(w, op, u, thunk, mask=None, accum=None, desc=None):
436+
"""Apply an index unary operator to each entry of a vector with a scalar thunk.
437+
438+
>>> from suitesparse_graphblas import scalar
439+
>>> w = vector_new(lib.GrB_INT64, 3)
440+
>>> u = vector_new(lib.GrB_INT64, 3)
441+
>>> set_int64(u, 10, 0)
442+
>>> set_int64(u, 20, 2)
443+
>>> s = scalar.scalar_new(lib.GrB_INT64)
444+
>>> scalar.set_int64(s, 0)
445+
>>> vector_apply_indexop(w, lib.GrB_ROWINDEX_INT64, u, s)
446+
>>> get_int64(w, 0) == 0
447+
True
448+
>>> get_int64(w, 2) == 2
449+
True
450+
451+
"""
452+
check_status(w, lib.GrB_Vector_apply_IndexOp_Scalar(
453+
w[0],
454+
ffi.NULL if mask is None else mask[0],
455+
ffi.NULL if accum is None else accum,
456+
op,
457+
u[0],
458+
thunk[0],
459+
ffi.NULL if desc is None else desc,
460+
))
461+
462+
435463
def vector_select(w, op, u, thunk, mask=None, accum=None, desc=None):
436464
"""Select entries from a vector using an index unary operator and scalar thunk.
437465

0 commit comments

Comments
 (0)