From 0de9ce9bf087431798e35d5e508eac8ea6bbb47b Mon Sep 17 00:00:00 2001 From: FamALouiz Date: Sun, 9 Mar 2025 16:25:49 +0100 Subject: [PATCH 01/11] Added implicit array abstract class --- pydatastructs/linear_data_structures/arrays.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pydatastructs/linear_data_structures/arrays.py b/pydatastructs/linear_data_structures/arrays.py index 2e0c3fd9..c97b64a4 100644 --- a/pydatastructs/linear_data_structures/arrays.py +++ b/pydatastructs/linear_data_structures/arrays.py @@ -471,3 +471,10 @@ def _modify(self): self._size = arr_new._size return new_indices return None + + +class ImplicitArray(Array): + ''' + Abstract class for implicit arrays + ''' + pass From aad738a18b04fe39fb72762b612cf30e5c5ab127 Mon Sep 17 00:00:00 2001 From: FamALouiz Date: Sun, 9 Mar 2025 18:17:46 +0100 Subject: [PATCH 02/11] Added python implementation of one dimensional implicit array --- .../linear_data_structures/arrays.py | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/pydatastructs/linear_data_structures/arrays.py b/pydatastructs/linear_data_structures/arrays.py index c97b64a4..ac78e019 100644 --- a/pydatastructs/linear_data_structures/arrays.py +++ b/pydatastructs/linear_data_structures/arrays.py @@ -478,3 +478,105 @@ class ImplicitArray(Array): Abstract class for implicit arrays ''' pass + + +class OneDimensionalImplicitArray(ImplicitArray): + """ + Represents one dimensional implicit arrays of fixed size. + + Parameters + ========== + function: function + A function which takes an integer as input and returns + the value of the element at that index. + dtype: type + A valid object type. + size: int + The number of elements in the array. + init: a python type + The initial value with which the element has + to be initialized. By default none, used only + when the data is not given. + backend: pydatastructs.Backend + The backend to be used. + Optional, by default, the best available + backend is used. + + Raises + ====== + + ValueError + When the number of elements in the list do not + match with the size. + More than three parameters are passed as arguments. + Types of arguments is not as mentioned in the docstring. + + Note + ==== + + At least one parameter should be passed as an argument along + with the dtype. + + Examples + ======== + + >>> from pydatastructs import OneDimensionalImplicitArray + >>> arr = OneDimensionalImplicitArray(lambda i: i+1, int, 5) + >>> arr[0] + 6 + >>> arr[1] + 7 + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Array_data_structure#One-dimensional_arrays + """ + + __slots__ = ['_size', '_dtype', '_function', '_init'] + + def __new__(cls, dtype=NoneType, *args, **kwargs): + backend = kwargs.get('backend', Backend.PYTHON) + # if backend == Backend.CPP: + # return _arrays.OneDimensionalImplicitArray(dtype, *args, **kwargs) + if dtype is NoneType: + raise ValueError("Data type is not defined.") + if len(args) < 1: + raise ValueError("Too few arguments to create a 1D implicit array, " + "pass the function of the array") + if len(args) > 2: + raise ValueError("Too many arguments to create a implicit 1D array, " + "pass the function of the array " + "and optionally the size of the array") + + obj = Array.__new__(cls) + obj._dtype = dtype + + if len(args) == 1: + if _check_type(args[0], function): + obj._function = args[0] + else: + raise TypeError("Expected type of function is function") + elif len(args) == 2: + if _check_type(args[0], function) and \ + _check_type(args[1], int): + obj._function = args[0] + obj._size = args[1] + elif _check_type(args[0], int) and \ + _check_type(args[1], function): + obj._function = args[1] + obj._size = args[0] + else: + raise TypeError("Expected type of function is function " + "and expected type of size is int") + + return obj + + def __getitem__(self, i): + if i >= self._size or i < 0: + raise IndexError(("Index, {} out of range, " + "[{}, {}).".format(i, 0, self._size))) + return self._function(i) + + def __len__(self): + return self._size From 3fa261b416c79b56af41830b5c36b09df1fd85f5 Mon Sep 17 00:00:00 2001 From: FamALouiz Date: Sun, 9 Mar 2025 18:24:09 +0100 Subject: [PATCH 03/11] Created python implicit array for cpp backend --- .../arrays/OneDimensionalImplicitArray.hpp | 164 ++++++++++++++++++ .../_backend/cpp/arrays/arrays.cpp | 7 + 2 files changed, 171 insertions(+) create mode 100644 pydatastructs/linear_data_structures/_backend/cpp/arrays/OneDimensionalImplicitArray.hpp diff --git a/pydatastructs/linear_data_structures/_backend/cpp/arrays/OneDimensionalImplicitArray.hpp b/pydatastructs/linear_data_structures/_backend/cpp/arrays/OneDimensionalImplicitArray.hpp new file mode 100644 index 00000000..174d6cfd --- /dev/null +++ b/pydatastructs/linear_data_structures/_backend/cpp/arrays/OneDimensionalImplicitArray.hpp @@ -0,0 +1,164 @@ +#ifndef LINEAR_DATA_STRUCTURES_ONEDIMENSIONALIMPLICITARRAY_HPP +#define LINEAR_DATA_STRUCTURES_ONEDIMENSIONALIMPLICITARRAY_HPP + +#define PY_SSIZE_T_CLEAN +#include +#include +#include +#include "Array.hpp" +#include "../../../../utils/_backend/cpp/utils.hpp" + +typedef struct +{ + PyObject_HEAD + size_t _size; + PyObject *_dtype; + PyObject *_function; + PyObject *_init; +} OneDimensionalImplicitArray; + +static void OneDimensionalImplicitArray_dealloc(OneDimensionalImplicitArray *self) +{ + Py_XDECREF(self->_dtype); + Py_XDECREF(self->_function); + Py_XDECREF(self->_init); + Py_TYPE(self)->tp_free(reinterpret_cast(self)); +} + +static PyObject *OneDimensionalImplicitArray___new__(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + OneDimensionalImplicitArray *self; + self = reinterpret_cast(type->tp_alloc(type, 0)); + size_t len_args = PyObject_Length(args); + + if (len_args < 1) + { + PyErr_SetString(PyExc_ValueError, "Too few arguments to create a 1D implicit array, pass the function of the array"); + return NULL; + } + if (len_args > 2) + { + PyErr_SetString(PyExc_ValueError, "Too many arguments to create an implicit 1D array, pass the function of the array and optionally the size of the array"); + return NULL; + } + + PyObject *function = PyObject_GetItem(args, PyZero); + if (!PyCallable_Check(function)) + { + PyErr_SetString(PyExc_TypeError, "Expected type of function is function"); + return NULL; + } + self->_function = function; + Py_INCREF(self->_function); + + PyObject *dtype = PyObject_GetItem(kwds, PyUnicode_FromString("dtype")); + if (dtype == nullptr) + { + PyErr_SetString(PyExc_ValueError, "Data type is not defined."); + return NULL; + } + self->_dtype = dtype; + Py_INCREF(self->_dtype); + + if (len_args == 2) + { + PyObject *size_obj = PyObject_GetItem(args, PyOne); + if (!PyLong_Check(size_obj)) + { + PyErr_SetString(PyExc_TypeError, "Expected type of size is int"); + return NULL; + } + self->_size = PyLong_AsSize_t(size_obj); + } + else + { + self->_size = 0; + } + + PyObject *init = PyObject_GetItem(kwds, PyUnicode_FromString("init")); + if (init == nullptr) + { + PyErr_Clear(); + self->_init = Py_None; + } + else + { + self->_init = init; + } + Py_INCREF(self->_init); + + return reinterpret_cast(self); +} + +static PyObject *OneDimensionalImplicitArray___getitem__(OneDimensionalImplicitArray *self, PyObject *arg) +{ + size_t idx = PyLong_AsUnsignedLong(arg); + if (idx >= self->_size) + { + PyErr_Format(PyExc_IndexError, "Index, %d, out of range, [%d, %d)", idx, 0, self->_size); + return NULL; + } + PyObject *result = PyObject_CallFunctionObjArgs(self->_function, PyLong_FromSize_t(idx), NULL); + if (result == NULL) + { + return NULL; + } + if (raise_exception_if_dtype_mismatch(result, self->_dtype)) + { + return NULL; + } + return result; +} + +static Py_ssize_t OneDimensionalImplicitArray___len__(OneDimensionalImplicitArray *self) +{ + return self->_size; +} + +static PyMappingMethods OneDimensionalImplicitArray_PyMappingMethods = { + (lenfunc)OneDimensionalImplicitArray___len__, + (binaryfunc)OneDimensionalImplicitArray___getitem__, + (objobjargproc)0, +}; + +static PyTypeObject OneDimensionalImplicitArrayType = { + /* tp_name */ PyVarObject_HEAD_INIT(NULL, 0) "OneDimensionalImplicitArray", + /* tp_basicsize */ sizeof(OneDimensionalImplicitArray), + /* tp_itemsize */ 0, + /* tp_dealloc */ (destructor)OneDimensionalImplicitArray_dealloc, + /* tp_print */ 0, + /* tp_getattr */ 0, + /* tp_setattr */ 0, + /* tp_reserved */ 0, + /* tp_repr */ 0, + /* tp_as_number */ 0, + /* tp_as_sequence */ 0, + /* tp_as_mapping */ &OneDimensionalImplicitArray_PyMappingMethods, + /* tp_hash */ 0, + /* tp_call */ 0, + /* tp_str */ 0, + /* tp_getattro */ 0, + /* tp_setattro */ 0, + /* tp_as_buffer */ 0, + /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + /* tp_doc */ 0, + /* tp_traverse */ 0, + /* tp_clear */ 0, + /* tp_richcompare */ 0, + /* tp_weaklistoffset */ 0, + /* tp_iter */ 0, + /* tp_iternext */ 0, + /* tp_methods */ 0, + /* tp_members */ 0, + /* tp_getset */ 0, + /* tp_base */ &ArrayType, + /* tp_dict */ 0, + /* tp_descr_get */ 0, + /* tp_descr_set */ 0, + /* tp_dictoffset */ 0, + /* tp_init */ 0, + /* tp_alloc */ 0, + /* tp_new */ OneDimensionalImplicitArray___new__, +}; + +#endif \ No newline at end of file diff --git a/pydatastructs/linear_data_structures/_backend/cpp/arrays/arrays.cpp b/pydatastructs/linear_data_structures/_backend/cpp/arrays/arrays.cpp index 974f38b5..d09af695 100644 --- a/pydatastructs/linear_data_structures/_backend/cpp/arrays/arrays.cpp +++ b/pydatastructs/linear_data_structures/_backend/cpp/arrays/arrays.cpp @@ -4,6 +4,7 @@ #include "DynamicArray.hpp" #include "DynamicOneDimensionalArray.hpp" #include "ArrayForTrees.hpp" +#include "OneDimensionalImplicitArray.hpp" static struct PyModuleDef arrays_struct = { PyModuleDef_HEAD_INIT, @@ -47,5 +48,11 @@ PyMODINIT_FUNC PyInit__arrays(void) { Py_INCREF(&ArrayForTreesType); PyModule_AddObject(arrays, "ArrayForTrees", reinterpret_cast(&ArrayForTreesType)); + if (PyType_Ready(&OneDimensionalImplicitArrayType) < 0) { + return NULL; + } + Py_INCREF(&OneDimensionalImplicitArrayType); + PyModule_AddObject(arrays, "OneDimensionalImplicitArray", reinterpret_cast(&OneDimensionalImplicitArrayType)); + return arrays; } From 3fc7cf4e2d4e63f7f68cdaca56faf4424deb9aae Mon Sep 17 00:00:00 2001 From: FamALouiz Date: Sun, 9 Mar 2025 18:25:00 +0100 Subject: [PATCH 04/11] Added backend cpp combatibility for implicit array --- pydatastructs/linear_data_structures/arrays.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pydatastructs/linear_data_structures/arrays.py b/pydatastructs/linear_data_structures/arrays.py index ac78e019..53002d77 100644 --- a/pydatastructs/linear_data_structures/arrays.py +++ b/pydatastructs/linear_data_structures/arrays.py @@ -537,8 +537,8 @@ class OneDimensionalImplicitArray(ImplicitArray): def __new__(cls, dtype=NoneType, *args, **kwargs): backend = kwargs.get('backend', Backend.PYTHON) - # if backend == Backend.CPP: - # return _arrays.OneDimensionalImplicitArray(dtype, *args, **kwargs) + if backend == Backend.CPP: + return _arrays.OneDimensionalImplicitArray(dtype, *args, **kwargs) if dtype is NoneType: raise ValueError("Data type is not defined.") if len(args) < 1: From d1b07c9574832415f0e5f4963338298e35e19f9f Mon Sep 17 00:00:00 2001 From: FamALouiz Date: Sun, 9 Mar 2025 18:52:08 +0100 Subject: [PATCH 05/11] Fixed bugs with array construction --- .../linear_data_structures/arrays.py | 50 ++++++++++--------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/pydatastructs/linear_data_structures/arrays.py b/pydatastructs/linear_data_structures/arrays.py index 53002d77..feea274c 100644 --- a/pydatastructs/linear_data_structures/arrays.py +++ b/pydatastructs/linear_data_structures/arrays.py @@ -6,7 +6,8 @@ __all__ = [ 'OneDimensionalArray', 'MultiDimensionalArray', - 'DynamicOneDimensionalArray' + 'DynamicOneDimensionalArray', + 'OneDimensionalImplicitArray', ] class Array(object): @@ -486,11 +487,11 @@ class OneDimensionalImplicitArray(ImplicitArray): Parameters ========== + dtype: type + A valid object type. function: function A function which takes an integer as input and returns the value of the element at that index. - dtype: type - A valid object type. size: int The number of elements in the array. init: a python type @@ -541,34 +542,31 @@ def __new__(cls, dtype=NoneType, *args, **kwargs): return _arrays.OneDimensionalImplicitArray(dtype, *args, **kwargs) if dtype is NoneType: raise ValueError("Data type is not defined.") - if len(args) < 1: - raise ValueError("Too few arguments to create a 1D implicit array, " - "pass the function of the array") + elif not _check_type(dtype, type): + raise TypeError("Expected type of dtype is type") + if len(args) <= 1: + raise ValueError("Too many arguments to create a implicit 1D array, " + "pass the function of the array " + "and the size of the array") if len(args) > 2: raise ValueError("Too many arguments to create a implicit 1D array, " "pass the function of the array " - "and optionally the size of the array") + "and the size of the array") obj = Array.__new__(cls) obj._dtype = dtype - if len(args) == 1: - if _check_type(args[0], function): - obj._function = args[0] - else: - raise TypeError("Expected type of function is function") - elif len(args) == 2: - if _check_type(args[0], function) and \ - _check_type(args[1], int): - obj._function = args[0] - obj._size = args[1] - elif _check_type(args[0], int) and \ - _check_type(args[1], function): - obj._function = args[1] - obj._size = args[0] - else: - raise TypeError("Expected type of function is function " - "and expected type of size is int") + if callable(args[0]) and \ + _check_type(args[1], int): + obj._function = args[0] + obj._size = args[1] + elif _check_type(args[0], int) and \ + callable(args[1]): + obj._function = args[1] + obj._size = args[0] + else: + raise TypeError("Expected type of function is function " + "and expected type of size is int") return obj @@ -580,3 +578,7 @@ def __getitem__(self, i): def __len__(self): return self._size + + @property + def _data(self): + return [self._function(i) for i in range(self._size)] \ No newline at end of file From 39124aebf7f328a0969f67a9fb577658fd63bee2 Mon Sep 17 00:00:00 2001 From: FamALouiz Date: Sun, 9 Mar 2025 18:53:31 +0100 Subject: [PATCH 06/11] Added 1d implicit array to linear_data_structures module --- pydatastructs/linear_data_structures/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pydatastructs/linear_data_structures/__init__.py b/pydatastructs/linear_data_structures/__init__.py index 057adc16..bb9d5719 100644 --- a/pydatastructs/linear_data_structures/__init__.py +++ b/pydatastructs/linear_data_structures/__init__.py @@ -11,7 +11,8 @@ OneDimensionalArray, DynamicOneDimensionalArray, MultiDimensionalArray, - ArrayForTrees + ArrayForTrees, + OneDimensionalImplicitArray ) __all__.extend(arrays.__all__) From e292ed90aa803cc2247f6d6220a7b4bebae3e5aa Mon Sep 17 00:00:00 2001 From: FamALouiz Date: Sun, 9 Mar 2025 18:59:36 +0100 Subject: [PATCH 07/11] Updated document docstring --- pydatastructs/linear_data_structures/arrays.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pydatastructs/linear_data_structures/arrays.py b/pydatastructs/linear_data_structures/arrays.py index feea274c..51ca4eec 100644 --- a/pydatastructs/linear_data_structures/arrays.py +++ b/pydatastructs/linear_data_structures/arrays.py @@ -515,14 +515,14 @@ class OneDimensionalImplicitArray(ImplicitArray): Note ==== - At least one parameter should be passed as an argument along + At least two parameters should be passed as an argument along with the dtype. Examples ======== >>> from pydatastructs import OneDimensionalImplicitArray - >>> arr = OneDimensionalImplicitArray(lambda i: i+1, int, 5) + >>> arr = OneDimensionalImplicitArray(int, lambda i: i+1, 5) >>> arr[0] 6 >>> arr[1] From 5ac7dbc9537564362b03f1570e3d04d6c1b46308 Mon Sep 17 00:00:00 2001 From: FamALouiz Date: Sun, 9 Mar 2025 19:10:15 +0100 Subject: [PATCH 08/11] Removed extra backspaces --- pydatastructs/linear_data_structures/arrays.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pydatastructs/linear_data_structures/arrays.py b/pydatastructs/linear_data_structures/arrays.py index 51ca4eec..9a4b8d79 100644 --- a/pydatastructs/linear_data_structures/arrays.py +++ b/pydatastructs/linear_data_structures/arrays.py @@ -552,10 +552,10 @@ def __new__(cls, dtype=NoneType, *args, **kwargs): raise ValueError("Too many arguments to create a implicit 1D array, " "pass the function of the array " "and the size of the array") - + obj = Array.__new__(cls) obj._dtype = dtype - + if callable(args[0]) and \ _check_type(args[1], int): obj._function = args[0] @@ -567,7 +567,7 @@ def __new__(cls, dtype=NoneType, *args, **kwargs): else: raise TypeError("Expected type of function is function " "and expected type of size is int") - + return obj def __getitem__(self, i): @@ -580,5 +580,5 @@ def __len__(self): return self._size @property - def _data(self): + def _data(self): return [self._function(i) for i in range(self._size)] \ No newline at end of file From 45856c4a174cb78ca38b254824e89ce6d90d0206 Mon Sep 17 00:00:00 2001 From: FamALouiz Date: Sun, 9 Mar 2025 19:20:31 +0100 Subject: [PATCH 09/11] Fixed styling + fixed bug with docstring --- .../_backend/cpp/arrays/OneDimensionalImplicitArray.hpp | 2 +- pydatastructs/linear_data_structures/arrays.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pydatastructs/linear_data_structures/_backend/cpp/arrays/OneDimensionalImplicitArray.hpp b/pydatastructs/linear_data_structures/_backend/cpp/arrays/OneDimensionalImplicitArray.hpp index 174d6cfd..f72246b7 100644 --- a/pydatastructs/linear_data_structures/_backend/cpp/arrays/OneDimensionalImplicitArray.hpp +++ b/pydatastructs/linear_data_structures/_backend/cpp/arrays/OneDimensionalImplicitArray.hpp @@ -161,4 +161,4 @@ static PyTypeObject OneDimensionalImplicitArrayType = { /* tp_new */ OneDimensionalImplicitArray___new__, }; -#endif \ No newline at end of file +#endif diff --git a/pydatastructs/linear_data_structures/arrays.py b/pydatastructs/linear_data_structures/arrays.py index 9a4b8d79..825d511f 100644 --- a/pydatastructs/linear_data_structures/arrays.py +++ b/pydatastructs/linear_data_structures/arrays.py @@ -524,9 +524,9 @@ class OneDimensionalImplicitArray(ImplicitArray): >>> from pydatastructs import OneDimensionalImplicitArray >>> arr = OneDimensionalImplicitArray(int, lambda i: i+1, 5) >>> arr[0] - 6 + 1 >>> arr[1] - 7 + 2 References ========== @@ -567,7 +567,7 @@ def __new__(cls, dtype=NoneType, *args, **kwargs): else: raise TypeError("Expected type of function is function " "and expected type of size is int") - + return obj def __getitem__(self, i): @@ -581,4 +581,4 @@ def __len__(self): @property def _data(self): - return [self._function(i) for i in range(self._size)] \ No newline at end of file + return [self._function(i) for i in range(self._size)] From fb2a3757a485e4bee3ba31b69aae22190fa26dca Mon Sep 17 00:00:00 2001 From: FamALouiz Date: Mon, 10 Mar 2025 23:29:58 +0100 Subject: [PATCH 10/11] Fixed bug with Implicit array cpp backend --- .../arrays/OneDimensionalImplicitArray.hpp | 76 ++++++++++--------- .../linear_data_structures/arrays.py | 2 +- 2 files changed, 43 insertions(+), 35 deletions(-) diff --git a/pydatastructs/linear_data_structures/_backend/cpp/arrays/OneDimensionalImplicitArray.hpp b/pydatastructs/linear_data_structures/_backend/cpp/arrays/OneDimensionalImplicitArray.hpp index f72246b7..db54f948 100644 --- a/pydatastructs/linear_data_structures/_backend/cpp/arrays/OneDimensionalImplicitArray.hpp +++ b/pydatastructs/linear_data_structures/_backend/cpp/arrays/OneDimensionalImplicitArray.hpp @@ -14,14 +14,12 @@ typedef struct size_t _size; PyObject *_dtype; PyObject *_function; - PyObject *_init; } OneDimensionalImplicitArray; static void OneDimensionalImplicitArray_dealloc(OneDimensionalImplicitArray *self) { Py_XDECREF(self->_dtype); Py_XDECREF(self->_function); - Py_XDECREF(self->_init); Py_TYPE(self)->tp_free(reinterpret_cast(self)); } @@ -31,26 +29,17 @@ static PyObject *OneDimensionalImplicitArray___new__(PyTypeObject *type, PyObjec self = reinterpret_cast(type->tp_alloc(type, 0)); size_t len_args = PyObject_Length(args); - if (len_args < 1) + if (len_args < 2) { - PyErr_SetString(PyExc_ValueError, "Too few arguments to create a 1D implicit array, pass the function of the array"); + PyErr_SetString(PyExc_ValueError, "Too few arguments to create a 1D implicit array, pass the function of the array and the size of the array"); return NULL; } if (len_args > 2) { - PyErr_SetString(PyExc_ValueError, "Too many arguments to create an implicit 1D array, pass the function of the array and optionally the size of the array"); + PyErr_SetString(PyExc_ValueError, "Too many arguments to create an implicit 1D array, pass the function of the array and the size of the array"); return NULL; } - PyObject *function = PyObject_GetItem(args, PyZero); - if (!PyCallable_Check(function)) - { - PyErr_SetString(PyExc_TypeError, "Expected type of function is function"); - return NULL; - } - self->_function = function; - Py_INCREF(self->_function); - PyObject *dtype = PyObject_GetItem(kwds, PyUnicode_FromString("dtype")); if (dtype == nullptr) { @@ -60,32 +49,26 @@ static PyObject *OneDimensionalImplicitArray___new__(PyTypeObject *type, PyObjec self->_dtype = dtype; Py_INCREF(self->_dtype); - if (len_args == 2) - { - PyObject *size_obj = PyObject_GetItem(args, PyOne); - if (!PyLong_Check(size_obj)) - { - PyErr_SetString(PyExc_TypeError, "Expected type of size is int"); - return NULL; - } - self->_size = PyLong_AsSize_t(size_obj); - } - else + PyObject *args0 = PyObject_GetItem(args, PyZero); + PyObject *args1 = PyObject_GetItem(args, PyOne); + + if (PyCallable_Check(args0) && PyLong_Check(args1)) { - self->_size = 0; + self->_function = args0; + Py_INCREF(self->_function); + self->_size = PyLong_AsSize_t(args1); } - - PyObject *init = PyObject_GetItem(kwds, PyUnicode_FromString("init")); - if (init == nullptr) + else if (PyCallable_Check(args1) && PyLong_Check(args0)) { - PyErr_Clear(); - self->_init = Py_None; + self->_function = args1; + Py_INCREF(self->_function); + self->_size = PyLong_AsSize_t(args0); } else { - self->_init = init; + PyErr_SetString(PyExc_TypeError, "Expected one function and one integer for size"); + return NULL; } - Py_INCREF(self->_init); return reinterpret_cast(self); } @@ -115,6 +98,31 @@ static Py_ssize_t OneDimensionalImplicitArray___len__(OneDimensionalImplicitArra return self->_size; } +static PyObject *OneDimensionalImplicitArray_get_data(OneDimensionalImplicitArray *self, void *closure) +{ + PyObject *list = PyList_New(self->_size); + if (!list) + { + return NULL; + } + for (size_t i = 0; i < self->_size; i++) + { + PyObject *item = PyObject_CallFunctionObjArgs(self->_function, PyLong_FromSize_t(i), NULL); + if (item == NULL) + { + Py_DECREF(list); + return NULL; + } + PyList_SET_ITEM(list, i, item); + } + return list; +} + +static PyGetSetDef OneDimensionalImplicitArray_getsetters[] = { + {"_data", (getter)OneDimensionalImplicitArray_get_data, NULL, "data", NULL}, + {NULL} /* Sentinel */ +}; + static PyMappingMethods OneDimensionalImplicitArray_PyMappingMethods = { (lenfunc)OneDimensionalImplicitArray___len__, (binaryfunc)OneDimensionalImplicitArray___getitem__, @@ -150,7 +158,7 @@ static PyTypeObject OneDimensionalImplicitArrayType = { /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, - /* tp_getset */ 0, + /* tp_getset */ OneDimensionalImplicitArray_getsetters, /* tp_base */ &ArrayType, /* tp_dict */ 0, /* tp_descr_get */ 0, diff --git a/pydatastructs/linear_data_structures/arrays.py b/pydatastructs/linear_data_structures/arrays.py index 825d511f..b759ecfa 100644 --- a/pydatastructs/linear_data_structures/arrays.py +++ b/pydatastructs/linear_data_structures/arrays.py @@ -539,7 +539,7 @@ class OneDimensionalImplicitArray(ImplicitArray): def __new__(cls, dtype=NoneType, *args, **kwargs): backend = kwargs.get('backend', Backend.PYTHON) if backend == Backend.CPP: - return _arrays.OneDimensionalImplicitArray(dtype, *args, **kwargs) + return _arrays.OneDimensionalImplicitArray(dtype=dtype, *args, **kwargs) if dtype is NoneType: raise ValueError("Data type is not defined.") elif not _check_type(dtype, type): From e5b19ae8f5aa1d70ed81c94d4379ec77410be4d3 Mon Sep 17 00:00:00 2001 From: FamALouiz Date: Mon, 10 Mar 2025 23:30:06 +0100 Subject: [PATCH 11/11] Added implicit array tests --- .../tests/test_arrays.py | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/pydatastructs/linear_data_structures/tests/test_arrays.py b/pydatastructs/linear_data_structures/tests/test_arrays.py index 88651011..977b2ee8 100644 --- a/pydatastructs/linear_data_structures/tests/test_arrays.py +++ b/pydatastructs/linear_data_structures/tests/test_arrays.py @@ -1,6 +1,6 @@ from pydatastructs.linear_data_structures import ( OneDimensionalArray, DynamicOneDimensionalArray, - MultiDimensionalArray, ArrayForTrees) + MultiDimensionalArray, ArrayForTrees, OneDimensionalImplicitArray) from pydatastructs.utils.misc_util import Backend from pydatastructs.utils.raises_util import raises from pydatastructs.utils import TreeNode @@ -155,3 +155,36 @@ def test_ArrayForTrees(): def test_cpp_ArrayForTrees(): _test_ArrayForTrees(Backend.CPP) + +def _test_OneDimensionalImplicitArray(backend: Backend): + ODIA = OneDimensionalImplicitArray + A = ODIA(int, lambda x: x + 1, 5, backend=backend) + assert A[0] == 1 + assert A[1] == 2 + assert A[2] == 3 + assert A[3] == 4 + assert A[4] == 5 + assert raises(IndexError, lambda: A[5]) + assert raises(IndexError, lambda: A[-1]) + assert str(A) == "[1, 2, 3, 4, 5]" + + A = ODIA(int, lambda x: (x + 2) ** 2, 10, backend=backend) + assert A[0] == 4 + assert A[1] == 9 + assert A[2] == 16 + assert A[3] == 25 + assert A[4] == 36 + assert A[5] == 49 + assert A[6] == 64 + assert A[7] == 81 + assert A[8] == 100 + assert A[9] == 121 + assert raises(IndexError, lambda: A[10]) + assert raises(IndexError, lambda: A[-1]) + assert str(A) == "[4, 9, 16, 25, 36, 49, 64, 81, 100, 121]" + +def test_OneDimensionalImplicitArray(): + _test_OneDimensionalImplicitArray(Backend.PYTHON) + +def test_cpp_OneDimensionalImplicitArray(): + _test_OneDimensionalImplicitArray(Backend.CPP)