def _build_range(rslice, stop_val): # if already a list, return it and its length if isinstance(rslice, list): return rslice, len(rslice), len(rslice) if rslice is None or rslice == _all_slice: return lib.GrB_ALL, 0, None start = rslice.start stop = rslice.stop step = rslice.step if start is None: start = 0 if stop is None: stop = stop_val if step is None: size = (stop - start) + 1 I = ffi.new("GrB_Index[2]", [start, stop]) ni = lib.GxB_RANGE elif step < 0: step = abs(step) if start < stop: size = 0 else: size = int((start - stop) / step) + 1 I = ffi.new("GrB_Index[3]", [start, stop, step]) ni = lib.GxB_BACKWARDS else: if start > stop or step == 0: size = 0 else: size = int((stop - start) / step) + 1 I = ffi.new("GrB_Index[3]", [start, stop, step]) ni = lib.GxB_STRIDE return I, ni, size
def test_check_status(): A = ffi.new("GrB_Matrix*") check_status(A, lib.GrB_Matrix_new(A, lib.GrB_BOOL, 2, 2)) with pytest.raises(exceptions.Panic): check_status(A, lib.GrB_PANIC) with pytest.raises(exceptions.Panic): check_status(A[0], lib.GrB_PANIC)
def new(T, nrows=lib.GxB_INDEX_MAX, ncols=lib.GxB_INDEX_MAX, *, free=free): """Create a new `GrB_Matrix` of type `T` and initialize it. The following example creates an eight bit unsigned 2x2 matrix: >>> A = new(lib.GrB_UINT8, 2, 2) >>> shape(A) (2, 2) The default value for `nrows` and `ncols` is `lib.GxB_INDEX_MAX` which creates a Matrix with maximal bounds: >>> A = new(lib.GrB_UINT8) >>> shape(A) == (lib.GxB_INDEX_MAX, lib.GxB_INDEX_MAX) True The `free` argument is called when the object is garbage collected, the default is `matrix.free()`. If `free` is None then there is no automatic garbage collection and it is up to the user to free the matrix. """ A = ffi.new("GrB_Matrix*") check_status(A, lib.GrB_Matrix_new(A, T, nrows, ncols)) if free: return ffi.gc(A, free) return A
def type(A): """Return the GraphBLAS type of the vector. >>> A = new(lib.GrB_UINT8) >>> type(A) == lib.GrB_UINT8 True """ T = ffi.new("GrB_Type*") check_status(A, lib.GxB_Matrix_type(T, A[0])) return T[0]
def nrows(A): """Return the number of rows in the matrix. >>> A = new(lib.GrB_UINT8, 2, 3) >>> nrows(A) 2 """ n = ffi.new("GrB_Index*") check_status(A, lib.GrB_Matrix_nrows(n, A[0])) return n[0]
def type(s): """Return the GraphBLAS type of the scalar. >>> S = new(lib.GrB_UINT8) >>> type(S) == lib.GrB_UINT8 True """ T = ffi.new("GrB_Type*") check_status(s, lib.GxB_Scalar_type(T, s[0])) return T[0]
def ncols(A): """Return the number of columns in the matrix. >>> A = new(lib.GrB_UINT8, 2, 3) >>> ncols(A) 3 """ n = ffi.new("GrB_Index*") check_status(A, lib.GrB_Matrix_ncols(n, A[0])) return n[0]
def nvals(A): """Return the number of stored elements in the matrix. >>> A = new(lib.GrB_UINT8, 2, 3) >>> nvals(A) 0 """ n = ffi.new("GrB_Index*") check_status(A, lib.GrB_Matrix_nvals(n, A[0])) return n[0]
def size(v): """Return the size of the vector. >>> v = new(lib.GrB_UINT8, 2) >>> size(v) == 2 True """ n = ffi.new("GrB_Index*") check_status(v, lib.GrB_Vector_size(n, v[0])) return n[0]
def format(A): """Return the format of the matrix. >>> A = new(lib.GrB_UINT8, 2, 2) >>> format(A) == lib.GxB_BY_ROW True """ format = ffi.new("GxB_Format_Value*") check_status(A, lib.GxB_Matrix_Option_get(A[0], lib.GxB_FORMAT, format)) return format[0]
def type(v): """Return the GraphBLAS type of the vector. >>> v = new(lib.GrB_UINT8, 2) >>> type(v) == lib.GrB_UINT8 True """ T = ffi.new("GrB_Type*") check_status(v, lib.GxB_Vector_type(T, v[0])) return T[0]
def bool(v, i): """Get a boolean value from the vector at position `i`. >>> v = new(lib.GrB_BOOL, 3) >>> set_bool(v, True, 2) >>> bool(v, 2) == True True """ value = ffi.new("bool*") check_status(v, lib.GrB_Vector_extractElement_BOOL(value, v[0], i)) return value[0]
def bool(A, i, j): """Get a boolean value from the matrix at row `i` column `j`. >>> A = new(lib.GrB_BOOL, 3, 3) >>> set_bool(A, True, 2, 2) >>> bool(A, 2, 2) == True True """ value = ffi.new("bool*") check_status(A, lib.GrB_Matrix_extractElement_BOOL(value, A[0], i, j)) return value[0]
def options_get(): """Get global library options. See SuiteSparse User Guide. >>> pprint(options_get()) {'bitmap_switch': [...], 'burble': ..., 'chunk': ..., 'format': ..., 'hyper_switch': ..., 'nthreads': ...} """ nthreads = ffi.new("int*") _check(lib.GxB_Global_Option_get(lib.GxB_GLOBAL_NTHREADS, nthreads)) chunk = ffi.new("double*") _check(lib.GxB_Global_Option_get(lib.GxB_GLOBAL_CHUNK, chunk)) burble = ffi.new("int*") _check(lib.GxB_Global_Option_get(lib.GxB_BURBLE, burble)) hyper_switch = ffi.new("double*") _check(lib.GxB_Global_Option_get(lib.GxB_HYPER_SWITCH, hyper_switch)) bitmap_switch = ffi.new("double[8]") _check(lib.GxB_Global_Option_get(lib.GxB_BITMAP_SWITCH, bitmap_switch)) format = ffi.new("GxB_Format_Value*") _check(lib.GxB_Global_Option_get(lib.GxB_FORMAT, format)) return dict( nthreads=nthreads[0], chunk=chunk[0], burble=burble[0], hyper_switch=hyper_switch[0], bitmap_switch=list(bitmap_switch), format=format[0], )
def nvals(v): """Return the number of stored elements in the vector. >>> v = new(lib.GrB_BOOL, 2) >>> nvals(v) 0 >>> set_bool(v, True, 1) >>> nvals(v) 1 """ n = ffi.new("GrB_Index*") check_status(v, lib.GrB_Vector_nvals(n, v[0])) return n[0]
def bool(s): """Get a boolean value from the scalar. >>> s = new(lib.GrB_BOOL) >>> set_bool(s, True) >>> bool(s) == True True """ value = ffi.new("bool*") res = check_status(s, lib.GxB_Scalar_extractElement_BOOL(value, s[0])) if res == exceptions.NoValue: return None return value[0]
def new(T, *, free=free): """Create a new `GxB_Scalar` of type `T` and initialize it. The `free` argument is called when the object is garbage collected, the default is `scalar.free()`. If `free` is None then there is no automatic garbage collection and it is up to the user to free the scalar. >>> S = new(lib.GrB_UINT8) """ s = ffi.new("GxB_Scalar*") check_status(s, lib.GxB_Scalar_new(s, T)) if free: return ffi.gc(s, free) return s
def options_set( nthreads=None, chunk=None, burble=None, hyper_switch=None, bitmap_switch=None, format=None, ): """Set global library options. This options are passed directly to SuiteSparse so see the SuiteSparse User Guide for details. - `nthreads`: Globals number of threads to use. - `chunk`: Chunk size for dividing parallel work. - `burble`: Switch to enable "burble" debug output. SuiteSparse must be compiled with burble turned on. - `hyper_switch`: Controls the hypersparsity of the internal data structure for a matrix. The parameter is typically in the range 0 to 1. - `bitmap_switch`: Controls when to switch to bitmap format. - `format`: Default global matrix data format. """ if nthreads is not None: nthreads = ffi.cast("int", nthreads) _check(lib.GxB_Global_Option_set(lib.GxB_GLOBAL_NTHREADS, nthreads)) if chunk is not None: chunk = ffi.cast("double", chunk) _check(lib.GxB_Global_Option_set(lib.GxB_GLOBAL_CHUNK, chunk)) if burble is not None: burble = ffi.cast("int", burble) _check(lib.GxB_Global_Option_set(lib.GxB_BURBLE, burble)) if hyper_switch is not None: hyper_switch = ffi.cast("double", hyper_switch) _check(lib.GxB_Global_Option_set(lib.GxB_HYPER_SWITCH, hyper_switch)) if bitmap_switch is not None: bitmap_switch = ffi.new("double[8]", bitmap_switch) _check(lib.GxB_Global_Option_set(lib.GxB_BITMAP_SWITCH, bitmap_switch)) if format is not None: format = ffi.cast("GxB_Format_Value*", format) _check(lib.GxB_Global_Option_set(lib.GxB_FORMAT, format))
def new(T, size=lib.GxB_INDEX_MAX, *, free=free): """Create a new `GrB_Vector` of type `T` and initialize it. >>> A = new(lib.GrB_UINT8, 2) >>> size(A) 2 The default `size` is `lib.GxB_INDEX_MAX`. >>> A = new(lib.GrB_UINT8) >>> size(A) == lib.GxB_INDEX_MAX True The `free` argument is called when the object is garbage collected, the default is `vector.free()`. If `free` is None then there is no automatic garbage collection and it is up to the user to free the vector. """ v = ffi.new("GrB_Vector*") check_status(v, lib.GrB_Vector_new(v, T, size)) if free: return ffi.gc(v, free) return v
def test_matrix_binfile_read_write(tmp_path): for opener in (Path.open, gzip.open, bz2.open, lzma.open): for format in (lib.GxB_BY_ROW, lib.GxB_BY_COL): for T in grb_types: for sparsity in (lib.GxB_HYPERSPARSE, lib.GxB_SPARSE, lib.GxB_BITMAP, lib.GxB_FULL): A = matrix.new(T, 2, 2) if T is not lib.GxB_FULL: for args in zip(*_test_elements(T)): f = _element_setters[T] check_status(A, f(A[0], *args)) else: Tone = _test_elements(T)[0][0] check_status( A[0], lib.GrB_assign( A, NULL, NULL, Tone, lib.GrB_ALL, 0, lib.GrB_ALL, 0, NULL, ), ) matrix.set_sparsity_control(A, sparsity) matrix.set_format(A, format) binfilef = tmp_path / "binfilewrite_test.binfile" binary.binwrite(A, binfilef, opener=opener) B = binary.binread(binfilef, opener=opener) assert matrix.type(A) == matrix.type(B) assert matrix.nrows(A) == matrix.nrows(B) assert matrix.ncols(A) == matrix.ncols(B) assert matrix.hyper_switch(A) == matrix.hyper_switch(B) assert matrix.bitmap_switch(A) == matrix.bitmap_switch(B) # assert matrix.sparsity_control(A) == matrix.sparsity_control(B) C = matrix.new(lib.GrB_BOOL, 2, 2) check_status( C, lib.GrB_Matrix_eWiseAdd_BinaryOp( C[0], NULL, NULL, _eq_ops[T], A[0], B[0], NULL), ) assert matrix.nvals(A) == matrix.nvals(B) == matrix.nvals( C) is_eq = ffi.new("bool*") check_status( C, lib.GrB_Matrix_reduce_BOOL(is_eq, NULL, lib.GrB_LAND_MONOID_BOOL, C[0], NULL), ) assert is_eq[0]
def test_complex(): s = ffi.new("GrB_Scalar*") success = lib.GrB_SUCCESS assert lib.GrB_Scalar_new(s, lib.GxB_FC64) == success assert lib.GxB_Scalar_setElement_FC64(s[0], 1j) == success assert lib.GrB_Scalar_free(s) == success
def sparsity_status(A): """Get the sparsity status of the matrix.""" sparsity_status = ffi.new("int32_t*") check_status(A, lib.GxB_Matrix_Option_get(A[0], lib.GxB_SPARSITY_STATUS, sparsity_status)) return sparsity_status[0]
def sparsity_control(A): """Get the sparsity control of the matrix.""" sparsity_control = ffi.new("int32_t*") check_status(A, lib.GxB_Matrix_Option_get(A[0], lib.GxB_SPARSITY_CONTROL, sparsity_control)) return sparsity_control[0]
def bitmap_switch(A): """Get the bitmap switch of the matrix.""" bitmap_switch = ffi.new("double*") check_status(A, lib.GxB_Matrix_Option_get(A[0], lib.GxB_BITMAP_SWITCH, bitmap_switch)) return bitmap_switch[0]
def hyper_switch(A): """Get the hyper switch of the matrix.""" hyper_switch = ffi.new("double*") check_status(A, lib.GxB_Matrix_Option_get(A[0], lib.GxB_HYPER_SWITCH, hyper_switch)) return hyper_switch[0]