Skip to content

Commit

Permalink
gh-218: impl types and array primitive in package
Browse files Browse the repository at this point in the history
  • Loading branch information
EgorOrachyov committed Aug 28, 2023
1 parent 11fd31c commit 413eaa7
Show file tree
Hide file tree
Showing 18 changed files with 432 additions and 29 deletions.
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# MIT License

Copyright (c) 2021-2022 SparseLinearAlgebra
Copyright (c) 2021-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
Expand Down
2 changes: 2 additions & 0 deletions include/spla.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,14 @@ SPLA_API spla_Status spla_Scalar_get_float(spla_Scalar s, float* value);
/* Array container creation and manipulation */

SPLA_API spla_Status spla_Array_make(spla_Array* v, spla_uint n_values, spla_Type type);
SPLA_API spla_Status spla_Array_get_n_values(spla_Array a, spla_uint* values);
SPLA_API spla_Status spla_Array_set_int(spla_Array a, spla_uint i, int value);
SPLA_API spla_Status spla_Array_set_uint(spla_Array a, spla_uint i, unsigned int value);
SPLA_API spla_Status spla_Array_set_float(spla_Array a, spla_uint i, float value);
SPLA_API spla_Status spla_Array_get_int(spla_Array a, spla_uint i, int* value);
SPLA_API spla_Status spla_Array_get_uint(spla_Array a, spla_uint i, unsigned int* value);
SPLA_API spla_Status spla_Array_get_float(spla_Array a, spla_uint i, float* value);
SPLA_API spla_Status spla_Array_resize(spla_Array a, spla_uint n);
SPLA_API spla_Status spla_Array_clear(spla_Array a);

//////////////////////////////////////////////////////////////////////////////////////
Expand Down
2 changes: 1 addition & 1 deletion python/LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# MIT License

Copyright (c) 2021-2022 SparseLinearAlgebra
Copyright (c) 2021-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
Expand Down
6 changes: 2 additions & 4 deletions python/example.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import os

os.environ["SPLA_PATH"] = "C:\\Users\\egoro\\Documents\\GitHub\\spla\\cmake-build-debug\\spla_x64.dll"

import pyspla

print(pyspla.Array.generate(dtype=pyspla.FLOAT, shape=3, dist=[100, 300]).to_list())
17 changes: 15 additions & 2 deletions python/pyspla/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@
on package exit. Library state finalized automatically.
"""

__copyright__ = "Copyright (c) 2021-2022 SparseLinearAlgebra"
__copyright__ = "Copyright (c) 2021-2023 SparseLinearAlgebra"

__license__ = """
MIT License
Expand All @@ -152,21 +152,34 @@
SOFTWARE.
"""

from .bridge import *

bridge.initialize()

from .library import *
from .op import *
from .object import *
from .schedule import *
from .type import *
from .array import *
from .matrix import *
from .vector import *
from .scalar import *
from .version import *
from .bridge import *

if not bridge.is_docs():
for t in BUILT_IN:
t._setup()

__version__ = VERSIONS[-1]

__all__ = [
"Type",
"INT",
"UINT",
"FLOAT",
"Object",
"Array",
"Matrix",
"Vector",
"Scalar",
Expand Down
2 changes: 1 addition & 1 deletion python/pyspla/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Main entry point.
"""

__copyright__ = "Copyright (c) 2021-2022 SparseLinearAlgebra"
__copyright__ = "Copyright (c) 2021-2023 SparseLinearAlgebra"

__license__ = """
MIT License
Expand Down
251 changes: 251 additions & 0 deletions python/pyspla/array.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
"""
Wrapped native (spla C API) array primitive 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 .type import Type, INT, UINT, FLOAT
from .object import Object
import random as rnd


class Array(Object):
"""
Generalized statically-typed dense linear array primitive.
Attributes
----------
- dtype : `Type` type of stored array elements
- shape : `2-tuple` shape of the array in form of two integers tuple (second dim is 1)
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
Details
-------
Array class support all spla C API vector functions.
It provides bind functionality as well as new functions/methods for better python user experience.
Array internally manages native optimized storage for values.
Reading and writing values into array is fast and has nearly no overhead.
"""

__slots__ = ["_dtype"]

def __init__(self, dtype=INT, shape=0, hnd=None, label=None):
"""
Creates new array of specified type and shape.
:param dtype: Type parametrization of a storage
:param shape: Size of the array
:param hnd: Optional native handle to retain
:param label: 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_Array_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: Type of stored values
"""
return self._dtype

@property
def shape(self):
"""
2-Tuple with shape of array where second value is always 1.
:return: Size of array as a tuple
"""

n_values = ctypes.c_uint(0)
check(backend().spla_Array_get_n_values(self._hnd, ctypes.byref(n_values)))
return int(n_values.value), 1

@property
def empty(self):
"""
Checks if array is empty (has 0-size) and returns true.
:return: True if array is empty
"""

return self.shape[0] == 0

def set(self, index, value):
"""
Set value at specified index.
:param index: Index at which value to set
:param value: Value to set, must be convertible to destination type
:return:
"""

check(self._dtype._array_set(self._hnd, ctypes.c_uint(index), self._dtype._c_type(value)))

def get(self, index):
"""
Get value at specified index.
:param index: Index at which to get value
:return: Value at specified index
"""

value = self._dtype._c_type(0)
check(self._dtype._array_get(self._hnd, ctypes.c_uint(index), ctypes.byref(value)))
return self._dtype._to_python(value)

def resize(self, shape=0):
"""
Resizes array to new size with desired num of values specified as shape.
:param shape: New array capacity
:return:
"""

check(backend().spla_Array_resize(self._hnd, ctypes.c_uint(shape)))

def clear(self):
"""
Clears array removing all elements, so it has 0 values.
:return:
"""

check(backend().spla_Array_clear(self._hnd))

def to_list(self):
"""
Read array data as a python list of values.
:return: List with values stored in the array
"""

values = list()
value = self._dtype._c_type(0)

for i in range(self.shape[0]):
check(self._dtype._array_get(self._hnd, ctypes.c_uint(i), ctypes.byref(value)))
values.append(self._dtype._to_python(value))

return values

@classmethod
def from_list(cls, values, dtype=INT, shape=None):
"""
Creates new array of desired type and shape and fills its content with `values` data.
:param values: List with values to fill array
:param dtype: Type of the array stored value
:param shape: Optional size of array, by default inferred from `values`
:return: Created array filled with values
"""

if shape is None:
shape = len(values)
assert shape >= len(values)
array = Array(dtype=dtype, shape=shape)
for i, v in enumerate(values):
array.set(i, v)
return array

@classmethod
def generate(cls, dtype=INT, shape=0, seed=None, dist=(0, 1)):
"""
Creates new array of desired type and shape and fills its content
with random values, generated using specified distribution.
:param dtype: Type of values array will have
:param shape: Size of the array (number of values)
:param seed: Optional seed to randomize generator
:param dist: Optional distribution for uniform generation of values
:return: Created array filled with values
"""

array = Array(dtype=dtype, shape=shape)

if seed is not None:
rnd.seed(seed)

if dtype is INT:
for i in range(shape):
array.set(i, rnd.randint(dist[0], dist[1]))
elif dtype is UINT:
for i in range(shape):
array.set(i, rnd.randint(dist[0], dist[1]))
elif dtype is FLOAT:
for i in range(shape):
array.set(i, rnd.uniform(dist[0], dist[1]))

return array

def __str__(self):
return str(self.to_list())

def __iter__(self):
return iter(self.to_list())

def __setitem__(self, key, value):
assert isinstance(key, int)
self.set(key, value)

def __getitem__(self, item):
assert isinstance(item, int)
return self.get(item)
Loading

0 comments on commit 413eaa7

Please sign in to comment.