From d71489bf486b302317dceadb0873953f2c75af08 Mon Sep 17 00:00:00 2001 From: Egor Orachev Date: Tue, 29 Aug 2023 21:23:32 +0300 Subject: [PATCH] gh-218: add math ops binding & start vector impl for package --- CMakeLists.txt | 1 + include/spla.h | 16 +++ python/example.py | 3 + python/pyspla/__init__.py | 2 + python/pyspla/array.py | 15 +-- python/pyspla/bridge.py | 41 ++++++- python/pyspla/descriptor.py | 51 +++++++++ python/pyspla/matrix.py | 33 +----- python/pyspla/op.py | 8 +- python/pyspla/scalar.py | 17 +-- python/pyspla/vector.py | 215 ++++++++++++++++++++++++++++++++---- src/binding/c_exec.cpp | 78 +++++++++++++ src/core/tmatrix.hpp | 1 + src/core/tvector.hpp | 1 + 14 files changed, 401 insertions(+), 81 deletions(-) create mode 100644 python/pyspla/descriptor.py create mode 100644 src/binding/c_exec.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c4486917e..e05b2fb2b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -353,6 +353,7 @@ add_library(spla SHARED src/binding/c_algorithm.cpp src/binding/c_array.cpp src/binding/c_config.hpp + src/binding/c_exec.cpp src/binding/c_library.cpp src/binding/c_matrix.cpp src/binding/c_memview.cpp diff --git a/include/spla.h b/include/spla.h index b5d35fb5d..fc6f3265e 100644 --- a/include/spla.h +++ b/include/spla.h @@ -297,6 +297,22 @@ SPLA_API spla_Status spla_Algorithm_tc(int* ntrins, spla_Matrix A, spla_Matrix B ////////////////////////////////////////////////////////////////////////////////////// +/* Scheduling and operations execution */ + +SPLA_API spla_Status spla_Exec_mxmT_masked(spla_Matrix R, spla_Matrix mask, spla_Matrix A, spla_Matrix B, spla_OpBinary op_multiply, spla_OpBinary op_add, spla_OpSelect op_select, spla_Scalar init, spla_Descriptor desc, spla_ScheduleTask* task); +SPLA_API spla_Status spla_Exec_mxv_masked(spla_Vector r, spla_Vector mask, spla_Matrix M, spla_Vector v, spla_OpBinary op_multiply, spla_OpBinary op_add, spla_OpSelect op_select, spla_Scalar init, spla_Descriptor desc, spla_ScheduleTask* task); +SPLA_API spla_Status spla_Exec_vxm_masked(spla_Vector r, spla_Vector mask, spla_Vector v, spla_Matrix M, spla_OpBinary op_multiply, spla_OpBinary op_add, spla_OpSelect op_select, spla_Scalar init, spla_Descriptor desc, spla_ScheduleTask* task); +SPLA_API spla_Status spla_Exec_m_reduce_by_row(spla_Vector r, spla_Matrix M, spla_OpBinary op_reduce, spla_Scalar init, spla_Descriptor desc, spla_ScheduleTask* task); +SPLA_API spla_Status spla_Exec_m_reduce(spla_Scalar r, spla_Scalar s, spla_Matrix M, spla_OpBinary op_reduce, spla_Descriptor desc, spla_ScheduleTask* task); +SPLA_API spla_Status spla_Exec_v_eadd(spla_Vector r, spla_Vector u, spla_Vector v, spla_OpBinary op, spla_Descriptor desc, spla_ScheduleTask* task); +SPLA_API spla_Status spla_Exec_v_eadd_fdb(spla_Vector r, spla_Vector v, spla_Vector fdb, spla_OpBinary op, spla_Descriptor desc, spla_ScheduleTask* task); +SPLA_API spla_Status spla_Exec_v_assign_masked(spla_Vector r, spla_Vector mask, spla_Scalar value, spla_OpBinary op_assign, spla_OpSelect op_select, spla_Descriptor desc, spla_ScheduleTask* task); +SPLA_API spla_Status spla_Exec_v_map(spla_Vector r, spla_Vector v, spla_OpUnary op, spla_Descriptor desc, spla_ScheduleTask* task); +SPLA_API spla_Status spla_Exec_v_reduce(spla_Scalar r, spla_Scalar s, spla_Vector v, spla_OpBinary op_reduce, spla_Descriptor desc, spla_ScheduleTask* task); +SPLA_API spla_Status spla_Exec_v_count_mf(spla_Scalar r, spla_Vector v, spla_Descriptor desc, spla_ScheduleTask* task); + +////////////////////////////////////////////////////////////////////////////////////// + #if defined(__cplusplus) } #endif diff --git a/python/example.py b/python/example.py index 836f224e0..85e279aa0 100644 --- a/python/example.py +++ b/python/example.py @@ -8,3 +8,6 @@ s = pyspla.Scalar(value=10, dtype=pyspla.INT) print(s) + +v = pyspla.Vector.from_lists([1, 2, 3], [-10, 100, 20], shape=10, dtype=pyspla.INT) +print(v.reduce(pyspla.INT.PLUS)) diff --git a/python/pyspla/__init__.py b/python/pyspla/__init__.py index 3d621d325..f6ae38b20 100644 --- a/python/pyspla/__init__.py +++ b/python/pyspla/__init__.py @@ -172,6 +172,7 @@ bridge.initialize() from .library import * +from .descriptor import * from .op import * from .object import * from .schedule import * @@ -190,6 +191,7 @@ "INT", "UINT", "FLOAT", + "Descriptor", "Op", "OpUnary", "OpBinary", diff --git a/python/pyspla/array.py b/python/pyspla/array.py index 9fefbc03e..44a1034bd 100644 --- a/python/pyspla/array.py +++ b/python/pyspla/array.py @@ -42,19 +42,12 @@ class Array(Object): Notes ----- - Array provides features for: - - - fill with values - - read-back by value - - source for vector construction - - source for matrix construction - Array typical usage: - - (1) Instantiate array primitive - - (2) Fill with values from your data - - (3) Use array to build entire vector or matrix - - (4) Read-back results of computations from vector or matrix + - Instantiate array primitive + - Fill with values from your data + - Use array to build entire vector or matrix + - Read-back results of computations from vector or matrix Details ------- diff --git a/python/pyspla/bridge.py b/python/pyspla/bridge.py index 01c79445e..74a5c5bca 100644 --- a/python/pyspla/bridge.py +++ b/python/pyspla/bridge.py @@ -296,9 +296,9 @@ def load_library(lib_path): _spla.spla_MemView_make.restype = _status_t _spla.spla_MemView_read.restype = _status_t _spla.spla_MemView_write.restype = _status_t - _spla.spla_MemView_get_buffer = _status_t - _spla.spla_MemView_get_size = _status_t - _spla.spla_MemView_is_mutable = _status_t + _spla.spla_MemView_get_buffer.restype = _status_t + _spla.spla_MemView_get_size.restype = _status_t + _spla.spla_MemView_is_mutable.restype = _status_t _spla.spla_MemView_make.argtypes = [_p_object_t, ctypes.c_void_p, ctypes.c_size_t, ctypes.c_int] _spla.spla_MemView_read.argtypes = [_object_t, ctypes.c_size_t, ctypes.c_size_t, ctypes.c_void_p] @@ -411,6 +411,41 @@ def load_library(lib_path): _spla.spla_Algorithm_pr.argtypes = [_p_object_t, _object_t, _float, _float, _object_t] _spla.spla_Algorithm_tc.argtypes = [_p_int, _object_t, _object_t, _object_t] + _spla.spla_Exec_mxmT_masked.restype = _status_t + _spla.spla_Exec_mxv_masked.restype = _status_t + _spla.spla_Exec_vxm_masked.restype = _status_t + _spla.spla_Exec_m_reduce_by_row.restype = _status_t + _spla.spla_Exec_m_reduce.restype = _status_t + _spla.spla_Exec_v_eadd.restype = _status_t + _spla.spla_Exec_v_eadd_fdb.restype = _status_t + _spla.spla_Exec_v_assign_masked.restype = _status_t + _spla.spla_Exec_v_map.restype = _status_t + _spla.spla_Exec_v_reduce.restype = _status_t + _spla.spla_Exec_v_count_mf.restype = _status_t + + _spla.spla_Exec_mxmT_masked.argtypes = \ + [_object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _p_object_t] + _spla.spla_Exec_mxv_masked.argtypes = \ + [_object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _p_object_t] + _spla.spla_Exec_vxm_masked.argtypes = \ + [_object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _p_object_t] + _spla.spla_Exec_m_reduce_by_row.argtypes = \ + [_object_t, _object_t, _object_t, _object_t, _object_t, _p_object_t] + _spla.spla_Exec_m_reduce.argtypes = \ + [_object_t, _object_t, _object_t, _object_t, _object_t, _p_object_t] + _spla.spla_Exec_v_eadd.argtypes = \ + [_object_t, _object_t, _object_t, _object_t, _object_t, _p_object_t] + _spla.spla_Exec_v_eadd_fdb.argtypes = \ + [_object_t, _object_t, _object_t, _object_t, _object_t, _p_object_t] + _spla.spla_Exec_v_assign_masked.argtypes = \ + [_object_t, _object_t, _object_t, _object_t, _object_t, _object_t, _p_object_t] + _spla.spla_Exec_v_map.argtypes = \ + [_object_t, _object_t, _object_t, _object_t, _p_object_t] + _spla.spla_Exec_v_reduce.argtypes = \ + [_object_t, _object_t, _object_t, _object_t, _object_t, _p_object_t] + _spla.spla_Exec_v_count_mf.argtypes = \ + [_object_t, _object_t, _object_t, _p_object_t] + def default_callback(status, msg, file, function, line, user_data): decoded_msg = msg.decode("utf-8") diff --git a/python/pyspla/descriptor.py b/python/pyspla/descriptor.py new file mode 100644 index 000000000..3cf67f09b --- /dev/null +++ b/python/pyspla/descriptor.py @@ -0,0 +1,51 @@ +""" +Wrapped native (spla C API) descriptor object implementation. +""" + +__copyright__ = "Copyright (c) 2021-2023 SparseLinearAlgebra" + +__license__ = """ +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +""" + +import ctypes + +from .bridge import backend, check +from .object import Object + + +class Descriptor(Object): + """ + Wrapper for a descriptor object from a library. + """ + + def __init__(self, label=None, hnd=None): + """ + Creates a new descriptor from existing hnd or making new for a buffer resource. + + :param label: optional: str. default: None. + MemView name for debugging. + + :param hnd: optional: ctypes.c_void_p. default: None. + MemView native void* handle to a C counterpart. + """ + + super().__init__(label, hnd) \ No newline at end of file diff --git a/python/pyspla/matrix.py b/python/pyspla/matrix.py index 1ae21f9b3..a8c503c20 100644 --- a/python/pyspla/matrix.py +++ b/python/pyspla/matrix.py @@ -36,37 +36,12 @@ class Matrix: Notes ----- - Matrix provides features for: - - - incremental creation - - build from values - - read-back by value - - (tbd) transposition - - (tbd) triangular lower - - (tbd) triangular upper - - (tbd) element-wise addition - - (tbd) element-wise subtraction - - matrix-vector product - - (tbd) matrix-matrix product - - (tbd) matrix-matrix kronecker product - - Matrix supports storage schemas: - - - cpu lil (list of lists, for incremental build) - - cpu dok (dictionary of keys, for incremental build and per-value reed back) - - cpu coo (coordinate matrix format) - - cpu csr (compressed sparse rows) - - cpu csc (compressed sparse columns) - - acc coo (opencl) - - acc csr (opencl) - - acc csc (opencl) - Matrix typical usage: - - (1) Instantiate matrix primitive - - (2) Build incrementally from yours data source - - (3) Matrix usage in a sequence of math operations - - (4) Read-back matrix data to python to analyse results + - Instantiate matrix primitive + - Build incrementally from yours data source + - Matrix usage in a sequence of math operations + - Read-back matrix data to python to analyse results Steps (2) and (4) requires internal format transformations and possible transfer of data from acc (GPU) side if acceleration was employed in computations. These steps may be very diff --git a/python/pyspla/op.py b/python/pyspla/op.py index b7a63cb40..106d0248b 100644 --- a/python/pyspla/op.py +++ b/python/pyspla/op.py @@ -71,7 +71,7 @@ def __init__(self, hnd, name, dtype_res, label=None): assert name assert dtype_res - super().__init__(hnd, label) + super().__init__(label, hnd) self._name = name self._dtype_res = dtype_res @@ -124,7 +124,7 @@ def __init__(self, hnd, name, dtype_res, dtype_arg0, label=None): Optional debug label to set for the object. """ - super().__init__(hnd, name, dtype_res, label) + super().__init__(hnd=hnd, name=name, dtype_res=dtype_res, label=label) self._dtype_arg0 = dtype_arg0 @@ -172,7 +172,7 @@ def __init__(self, hnd, name, dtype_res, dtype_arg0, dtype_arg1, label=None): Optional debug label to set for the object. """ - super().__init__(hnd, name, dtype_res, label) + super().__init__(hnd=hnd, name=name, dtype_res=dtype_res, label=label) self._dtype_arg0 = dtype_arg0 self._dtype_arg1 = dtype_arg1 @@ -224,7 +224,7 @@ def __init__(self, hnd, name, dtype_arg0, label=None): from .type import BOOL - super().__init__(hnd, name, BOOL, label) + super().__init__(hnd=hnd, name=name, dtype_res=BOOL, label=label) self._dtype_arg0 = dtype_arg0 diff --git a/python/pyspla/scalar.py b/python/pyspla/scalar.py index b30591d63..8eeca475e 100644 --- a/python/pyspla/scalar.py +++ b/python/pyspla/scalar.py @@ -40,19 +40,12 @@ class Scalar(Object): Notes ----- - Scalar provides features for: - - - pack native value - - unpack native value - - pass value as a param to some operation - - get scalar as an operation result - Scalar typical usage: - - (1) Create scalar from python value - - (2) Pass scalar as argument to matrix/vector operation - - (3) Get scalar as a return value of some operation - - (4) Unpack value on python side + - Create scalar from python value + - Pass scalar as argument to matrix/vector operation + - Get scalar as a return value of some operation + - Unpack value on python side Avoid intensive creation of scalar values. Prefer python native types. Use scalars only if you want to parametrise matrix/vector operations. @@ -129,7 +122,7 @@ def set(self, value=None): Optional value to store in scalar. """ - check(self._dtype._scalar_set(self._hnd, self._dtype._c_type(value))) + check(self._dtype._scalar_set(self._hnd, self._dtype._c_type(value if value else 0))) def get(self): """ diff --git a/python/pyspla/vector.py b/python/pyspla/vector.py index 105aa4f11..019c407ee 100644 --- a/python/pyspla/vector.py +++ b/python/pyspla/vector.py @@ -28,35 +28,29 @@ import ctypes +from .bridge import backend, check +from .type import Type, INT, UINT +from .object import Object +from .memview import MemView +from .scalar import Scalar +from .matrix import Matrix +from .descriptor import Descriptor +from .op import OpUnary, OpBinary, OpSelect -class Vector: + +class Vector(Object): """ Generalized statically-typed sparse storage-invariant vector primitive. Notes ----- - Vector provides features for: - - - incremental creation - - build from values - - read-back by value - - reduction to scalar - - (tbd) element-wise addition - - (tbd) element-wise subtraction - - matrix-vector product - - Vector supports storage schemas: - - - cpu dense - - acc dense (opencl) - Vector typical usage: - - (1) Instantiate vector primitive - - (2) Build incrementally from yours data source - - (3) Vector usage in a sequence of math operations - - (4) Read-back vector data to python to analyse results + - Instantiate vector primitive + - Build incrementally from yours data source + - Vector usage in a sequence of math operations + - Read-back vector data to python to analyse results Steps (2) and (4) requires internal format transformations and possible transfer of data from acc (GPU) side if acceleration was employed in computations. These steps may be very @@ -76,5 +70,182 @@ class Vector: using one of built-in OpenCL or CUDA accelerators. """ - def __init__(self): - pass + def __init__(self, shape, dtype=INT, hnd=None, label=None): + """ + Creates new vector of specified type and shape. + + :param dtype: Type. + Type parametrization of a storage. + + :param shape: int. + Vector size. + + :param hnd: optional: ctypes.c_void_p. default: None. + Optional native handle to retain. + + :param label: optional: str. default: None. + Optional label to assign. + """ + + super().__init__(None, None) + + assert dtype + assert shape + assert shape > 0 + assert issubclass(dtype, Type) + + self._dtype = dtype + + if not hnd: + hnd = ctypes.c_void_p(0) + check(backend().spla_Vector_make(ctypes.byref(hnd), ctypes.c_uint(shape), dtype._hnd)) + + super().__init__(label, hnd) + + @property + def dtype(self): + """ + Type used for storage parametrization of this container. + """ + return self._dtype + + @property + def n_rows(self): + """ + Number of rows in the vector. + """ + count = ctypes.c_uint(0) + check(backend().spla_Vector_get_n_rows(self._hnd, ctypes.byref(count))) + return int(count.value) + + @property + def shape(self): + """ + 2-Tuple with shape of vector where second value is always 1. + """ + + return self.n_rows, 1 + + def build(self, ii_view: MemView, vv_view: MemView): + """ + Builds vector content from a raw memory view resources. + + :param ii_view: MemView. + View to keys of vector to assign. + + :param vv_view: MemView. + View to actual values to store. + """ + + assert ii_view + assert vv_view + + check(backend().spla_Vector_build(self._hnd, ii_view._hnd, vv_view._hnd)) + + def read(self): + """ + Read the content of the vector as a MemView of keys and values. + + :return: tuple (MemView, MemView) objects with view to the vector keys and vector values. + """ + + ii_view_hnd = ctypes.c_void_p(0) + vv_view_hnd = ctypes.c_void_p(0) + check(backend().spla_Vector_read(self._hnd, ctypes.byref(ii_view_hnd), ctypes.byref(vv_view_hnd))) + return MemView(hnd=ii_view_hnd, owner=self), MemView(hnd=vv_view_hnd, owner=self) + + def to_lists(self): + """ + Read vector data as a python lists of keys and values. + + :return: Tuple (List, List) with the vector keys and vector values. + """ + + keys, values = self.read() + count = int(keys.size / ctypes.sizeof(UINT._c_type)) + + buffer_keys = (UINT._c_type * count)() + buffer_values = (self._dtype._c_type * count)() + + check(backend().spla_MemView_read(keys._hnd, ctypes.c_size_t(0), ctypes.sizeof(buffer_keys), buffer_keys)) + check(backend().spla_MemView_read(values._hnd, ctypes.c_size_t(0), ctypes.sizeof(buffer_values), buffer_values)) + + return list(buffer_keys), list(buffer_values) + + @classmethod + def from_lists(cls, ii: list, vv: list, shape, dtype=INT): + """ + Build vector from a list of sorted keys and associated values to store in vector. + List with keys `ii` must index entries from range [0, shape-1] and all keys must be sorted. + + :param ii: list[UINT]. + List with integral keys of entries. + + :param vv: list[Type]. + List with values to store in the vector. + + :param shape: int. + Vector size. + + :param dtype: + Type of storage parametrization for vector. + + :return: Created vector filled with values. + """ + + assert ii + assert vv + assert len(ii) == len(vv) + assert shape > 0 + + count = len(ii) + + c_ii = (UINT._c_type * count)(*ii) + c_vv = (dtype._c_type * count)(*vv) + + view_ii = MemView(buffer=c_ii, size=ctypes.sizeof(c_ii), mutable=False) + view_vv = MemView(buffer=c_vv, size=ctypes.sizeof(c_vv), mutable=False) + + v = Vector(shape=shape, dtype=dtype) + v.build(view_ii, view_vv) + + return v + + def reduce(self, op_reduce, r=None, init=None, desc=None): + """ + Reduce vector elements. + + :param op_reduce: OpBinary. + Binary operation to apply for reduction of vector elements. + + :param r: optional: Scalar: default: 0. + Optional scalar to store result of reduction. + + :param init: optional: Scalar: default: 0. + Optional neutral init value for reduction. + + :param desc: optional: Descriptor. default: None. + Optional descriptor object to configure the execution. + + :return: Scalar value with result. + """ + + if r is None: + r = Scalar(dtype=self.dtype) + if init is None: + init = Scalar(dtype=self.dtype, value=0) + + check(backend().spla_Exec_v_reduce(r.hnd, init.hnd, self.hnd, op_reduce.hnd, + self._get_desc(desc), self._get_task(None))) + + return r + + def __iter__(self): + keys, values = self.to_lists() + return zip(keys, values) + + def _get_desc(self, desc: Descriptor): + return desc.hnd if desc else ctypes.c_void_p(0) + + def _get_task(self, task): + return ctypes.POINTER(ctypes.c_void_p)() diff --git a/src/binding/c_exec.cpp b/src/binding/c_exec.cpp new file mode 100644 index 000000000..6c8859c19 --- /dev/null +++ b/src/binding/c_exec.cpp @@ -0,0 +1,78 @@ +/**********************************************************************************/ +/* This file is part of spla project */ +/* https://github.com/JetBrains-Research/spla */ +/**********************************************************************************/ +/* MIT License */ +/* */ +/* Copyright (c) 2023 SparseLinearAlgebra */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining a copy */ +/* of this software and associated documentation files (the "Software"), to deal */ +/* in the Software without restriction, including without limitation the rights */ +/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ +/* copies of the Software, and to permit persons to whom the Software is */ +/* furnished to do so, subject to the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be included in all */ +/* copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ +/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ +/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ +/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ +/* SOFTWARE. */ +/**********************************************************************************/ + +#include "c_config.hpp" + +#define SPLA_WRAP_EXEC(what, ...) \ + spla::ref_ptr ref_task; \ + const spla::Status status = spla::what(__VA_ARGS__, as_ref(desc), (task ? &ref_task : nullptr)); \ + if (status == spla::Status::Ok && task) { \ + *task = as_ptr(ref_task.release()); \ + return SPLA_STATUS_OK; \ + } \ + return to_c_status(status); + +#define AS_S(x) as_ref(x) +#define AS_M(x) as_ref(x) +#define AS_V(x) as_ref(x) +#define AS_OB(x) as_ref(x) +#define AS_OU(x) as_ref(x) +#define AS_OS(x) as_ref(x) + +spla_Status spla_Exec_mxmT_masked(spla_Matrix R, spla_Matrix mask, spla_Matrix A, spla_Matrix B, spla_OpBinary op_multiply, spla_OpBinary op_add, spla_OpSelect op_select, spla_Scalar init, spla_Descriptor desc, spla_ScheduleTask* task) { + SPLA_WRAP_EXEC(exec_mxmT_masked, AS_M(R), AS_M(mask), AS_M(A), AS_M(B), AS_OB(op_multiply), AS_OB(op_add), AS_OS(op_select), AS_S(init)); +} +spla_Status spla_Exec_mxv_masked(spla_Vector r, spla_Vector mask, spla_Matrix M, spla_Vector v, spla_OpBinary op_multiply, spla_OpBinary op_add, spla_OpSelect op_select, spla_Scalar init, spla_Descriptor desc, spla_ScheduleTask* task) { + SPLA_WRAP_EXEC(exec_mxv_masked, AS_V(r), AS_V(mask), AS_M(M), AS_V(v), AS_OB(op_multiply), AS_OB(op_add), AS_OS(op_select), AS_S(init)); +} +spla_Status spla_Exec_vxm_masked(spla_Vector r, spla_Vector mask, spla_Vector v, spla_Matrix M, spla_OpBinary op_multiply, spla_OpBinary op_add, spla_OpSelect op_select, spla_Scalar init, spla_Descriptor desc, spla_ScheduleTask* task) { + SPLA_WRAP_EXEC(exec_vxm_masked, AS_V(r), AS_V(mask), AS_V(v), AS_M(M), AS_OB(op_multiply), AS_OB(op_add), AS_OS(op_select), AS_S(init)); +} +spla_Status spla_Exec_m_reduce_by_row(spla_Vector r, spla_Matrix M, spla_OpBinary op_reduce, spla_Scalar init, spla_Descriptor desc, spla_ScheduleTask* task) { + SPLA_WRAP_EXEC(exec_m_reduce_by_row, AS_V(r), AS_M(M), AS_OB(op_reduce), AS_S(init)); +} +spla_Status spla_Exec_m_reduce(spla_Scalar r, spla_Scalar s, spla_Matrix M, spla_OpBinary op_reduce, spla_Descriptor desc, spla_ScheduleTask* task) { + SPLA_WRAP_EXEC(exec_m_reduce, AS_S(r), AS_S(s), AS_M(M), AS_OB(op_reduce)); +} +spla_Status spla_Exec_v_eadd(spla_Vector r, spla_Vector u, spla_Vector v, spla_OpBinary op, spla_Descriptor desc, spla_ScheduleTask* task) { + SPLA_WRAP_EXEC(exec_v_eadd, AS_V(r), AS_V(u), AS_V(v), AS_OB(op)); +} +spla_Status spla_Exec_v_eadd_fdb(spla_Vector r, spla_Vector v, spla_Vector fdb, spla_OpBinary op, spla_Descriptor desc, spla_ScheduleTask* task) { + SPLA_WRAP_EXEC(exec_v_eadd_fdb, AS_V(r), AS_V(v), AS_V(fdb), AS_OB(op)); +} +spla_Status spla_Exec_v_assign_masked(spla_Vector r, spla_Vector mask, spla_Scalar value, spla_OpBinary op_assign, spla_OpSelect op_select, spla_Descriptor desc, spla_ScheduleTask* task) { + SPLA_WRAP_EXEC(exec_v_assign_masked, AS_V(r), AS_V(mask), AS_S(value), AS_OB(op_assign), AS_OS(op_select)); +} +spla_Status spla_Exec_v_map(spla_Vector r, spla_Vector v, spla_OpUnary op, spla_Descriptor desc, spla_ScheduleTask* task) { + SPLA_WRAP_EXEC(exec_v_map, AS_V(r), AS_V(v), AS_OU(op)); +} +spla_Status spla_Exec_v_reduce(spla_Scalar r, spla_Scalar s, spla_Vector v, spla_OpBinary op_reduce, spla_Descriptor desc, spla_ScheduleTask* task) { + SPLA_WRAP_EXEC(exec_v_reduce, AS_S(r), AS_S(s), AS_V(v), AS_OB(op_reduce)); +} +spla_Status spla_Exec_v_count_mf(spla_Scalar r, spla_Vector v, spla_Descriptor desc, spla_ScheduleTask* task) { + SPLA_WRAP_EXEC(exec_v_count_mf, AS_S(r), AS_V(v)); +} \ No newline at end of file diff --git a/src/core/tmatrix.hpp b/src/core/tmatrix.hpp index d4c62cf05..ed158886e 100644 --- a/src/core/tmatrix.hpp +++ b/src/core/tmatrix.hpp @@ -242,6 +242,7 @@ namespace spla { coo.Ai.resize(elements_count); coo.Aj.resize(elements_count); coo.Ax.resize(elements_count); + coo.values = uint(elements_count); keys1->read(0, key_size * elements_count, coo.Ai.data()); keys2->read(0, key_size * elements_count, coo.Aj.data()); diff --git a/src/core/tvector.hpp b/src/core/tvector.hpp index ce9d7f990..5d7ca4712 100644 --- a/src/core/tvector.hpp +++ b/src/core/tvector.hpp @@ -287,6 +287,7 @@ namespace spla { coo.Ai.resize(elements_count); coo.Ax.resize(elements_count); + coo.values = uint(elements_count); keys->read(0, key_size * elements_count, coo.Ai.data()); values->read(0, value_size * elements_count, coo.Ax.data());