pythonic-fp-numpy 0.1.2__tar.gz → 1.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pythonic_fp_numpy-1.1.0/PKG-INFO +51 -0
- pythonic_fp_numpy-1.1.0/README.md +27 -0
- {pythonic_fp_numpy-0.1.2 → pythonic_fp_numpy-1.1.0}/pyproject.toml +47 -34
- {pythonic_fp_numpy-0.1.2 → pythonic_fp_numpy-1.1.0}/src/pythonic_fp/numpy/__init__.py +6 -11
- pythonic_fp_numpy-1.1.0/src/pythonic_fp/numpy/hashable_wrapped_ndarray.py +411 -0
- pythonic_fp_numpy-0.1.2/.gitignore +0 -7
- pythonic_fp_numpy-0.1.2/CHANGELOG.rst +0 -54
- pythonic_fp_numpy-0.1.2/PKG-INFO +0 -62
- pythonic_fp_numpy-0.1.2/README.rst +0 -36
- pythonic_fp_numpy-0.1.2/src/pythonic_fp/numpy/__init__.pyi +0 -0
- pythonic_fp_numpy-0.1.2/src/pythonic_fp/numpy/hashable_wrapped_ndarray.py +0 -235
- pythonic_fp_numpy-0.1.2/src/pythonic_fp/numpy/hashable_wrapped_ndarray.pyi +0 -48
- pythonic_fp_numpy-0.1.2/tests/hashable_wrapped_ndarray/test_HWrapNDArrayNumber.py +0 -86
- {pythonic_fp_numpy-0.1.2 → pythonic_fp_numpy-1.1.0}/LICENSE +0 -0
- {pythonic_fp_numpy-0.1.2 → pythonic_fp_numpy-1.1.0}/src/pythonic_fp/numpy/py.typed +0 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pythonic-fp-numpy
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: FP tools for Numpy
|
|
5
|
+
Keywords: numpy,ndarray,hashable,wrap
|
|
6
|
+
Author-email: "Geoffrey R. Scheller" <geoffrey@scheller.com>
|
|
7
|
+
Requires-Python: >=3.14
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Framework :: Pytest
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
16
|
+
Classifier: Typing :: Typed
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: numpy>=2.3.4
|
|
19
|
+
Project-URL: Changelog, https://github.com/grscheller/pythonic-fp-numpy/blob/main/CHANGELOG.md
|
|
20
|
+
Project-URL: Documentation, https://grscheller.github.io/pythonic-fp-numpy/release/html/
|
|
21
|
+
Project-URL: Homepage, https://grscheller.github.io/pythonic-fp/
|
|
22
|
+
Project-URL: Source, https://github.com/grscheller/pythonic-fp-numpy
|
|
23
|
+
|
|
24
|
+
# Pythonic FP - FP Numpy
|
|
25
|
+
|
|
26
|
+
Python package implementing functional programming tools for NumPy.
|
|
27
|
+
|
|
28
|
+
PyPI project
|
|
29
|
+
[pythonic-fp-numpy](https://pypi.org/project/pythonic-fp-numpy).
|
|
30
|
+
Part of the
|
|
31
|
+
[pythonic-fp](https://grscheller.github.io/pythonic-fp/)
|
|
32
|
+
PyPI projects.
|
|
33
|
+
|
|
34
|
+
## Documentation
|
|
35
|
+
|
|
36
|
+
Documentation and other links for this project are hosted on
|
|
37
|
+
[GitHub Pages](https://grscheller.github.io/pythonic-fp/projects/numpy.html).
|
|
38
|
+
|
|
39
|
+
### Modules
|
|
40
|
+
|
|
41
|
+
#### Module hashable_wrapped_ndarray
|
|
42
|
+
|
|
43
|
+
- wrap readonly NDArrays to make them hashable
|
|
44
|
+
- prioritize performance over safety
|
|
45
|
+
- see PyPI project boring-math-abstract-algebra for a use case
|
|
46
|
+
|
|
47
|
+
## Copyright and License
|
|
48
|
+
|
|
49
|
+
Copyright (c) 2025-2026 Geoffrey R. Scheller. Licensed under the Apache
|
|
50
|
+
License, Version 2.0. See the LICENSE file for details.
|
|
51
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Pythonic FP - FP Numpy
|
|
2
|
+
|
|
3
|
+
Python package implementing functional programming tools for NumPy.
|
|
4
|
+
|
|
5
|
+
PyPI project
|
|
6
|
+
[pythonic-fp-numpy](https://pypi.org/project/pythonic-fp-numpy).
|
|
7
|
+
Part of the
|
|
8
|
+
[pythonic-fp](https://grscheller.github.io/pythonic-fp/)
|
|
9
|
+
PyPI projects.
|
|
10
|
+
|
|
11
|
+
## Documentation
|
|
12
|
+
|
|
13
|
+
Documentation and other links for this project are hosted on
|
|
14
|
+
[GitHub Pages](https://grscheller.github.io/pythonic-fp/projects/numpy.html).
|
|
15
|
+
|
|
16
|
+
### Modules
|
|
17
|
+
|
|
18
|
+
#### Module hashable_wrapped_ndarray
|
|
19
|
+
|
|
20
|
+
- wrap readonly NDArrays to make them hashable
|
|
21
|
+
- prioritize performance over safety
|
|
22
|
+
- see PyPI project boring-math-abstract-algebra for a use case
|
|
23
|
+
|
|
24
|
+
## Copyright and License
|
|
25
|
+
|
|
26
|
+
Copyright (c) 2025-2026 Geoffrey R. Scheller. Licensed under the Apache
|
|
27
|
+
License, Version 2.0. See the LICENSE file for details.
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["flit_core>=3.12,<4"]
|
|
3
|
+
build-backend = "flit_core.buildapi"
|
|
4
|
+
|
|
1
5
|
[project]
|
|
2
6
|
name = "pythonic-fp-numpy"
|
|
3
|
-
version = "
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
authors = [
|
|
7
|
+
version = "1.1.0"
|
|
8
|
+
description = "FP tools for Numpy"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.14" # floor: PEP 649/749 deferred annotations — class-level self-reference possible NameErrors on <3.14
|
|
11
|
+
authors = [
|
|
12
|
+
{ name = "Geoffrey R. Scheller", email = "geoffrey@scheller.com" },
|
|
13
|
+
]
|
|
8
14
|
keywords = [
|
|
9
15
|
"numpy",
|
|
10
16
|
"ndarray",
|
|
@@ -12,69 +18,76 @@ keywords = [
|
|
|
12
18
|
"wrap",
|
|
13
19
|
]
|
|
14
20
|
classifiers = [
|
|
15
|
-
"Development Status ::
|
|
21
|
+
"Development Status :: 3 - Alpha",
|
|
16
22
|
"Framework :: Pytest",
|
|
17
23
|
"Intended Audience :: Developers",
|
|
18
24
|
"License :: OSI Approved :: Apache Software License",
|
|
19
25
|
"Operating System :: OS Independent",
|
|
20
|
-
"Programming Language :: Python :: 3.
|
|
26
|
+
"Programming Language :: Python :: 3.14",
|
|
27
|
+
"Programming Language :: Python :: 3.15",
|
|
21
28
|
"Typing :: Typed",
|
|
22
29
|
]
|
|
23
30
|
dependencies = [
|
|
24
31
|
"numpy>=2.3.4",
|
|
25
32
|
]
|
|
26
|
-
dynamic = ["description"]
|
|
27
33
|
|
|
28
34
|
[project.urls]
|
|
29
|
-
Changelog = "https://github.com/grscheller/pythonic-fp-numpy/blob/main/CHANGELOG.
|
|
30
|
-
Documentation =
|
|
31
|
-
Homepage = "https://grscheller.github.io/pythonic-fp/
|
|
35
|
+
Changelog = "https://github.com/grscheller/pythonic-fp-numpy/blob/main/CHANGELOG.md"
|
|
36
|
+
Documentation ="https://grscheller.github.io/pythonic-fp-numpy/release/html/"
|
|
37
|
+
Homepage = "https://grscheller.github.io/pythonic-fp/"
|
|
32
38
|
Source = "https://github.com/grscheller/pythonic-fp-numpy"
|
|
33
39
|
|
|
34
|
-
[
|
|
40
|
+
[dependency-groups]
|
|
41
|
+
docs = [
|
|
42
|
+
"furo>=2025.12.19",
|
|
43
|
+
"sphinx>=9.1",
|
|
44
|
+
]
|
|
35
45
|
test = [
|
|
36
|
-
"boring-math-abstract-algebra>=1.1.0",
|
|
37
46
|
"pytest>=8.4.1",
|
|
47
|
+
"boring-math-abstract-algebra",
|
|
38
48
|
]
|
|
39
49
|
|
|
40
|
-
[build-system]
|
|
41
|
-
requires = ["flit_core>=3.12,<4"]
|
|
42
|
-
build-backend = "flit_core.buildapi"
|
|
43
|
-
|
|
44
50
|
[tool.flit.module]
|
|
45
51
|
name = "pythonic_fp.numpy"
|
|
46
52
|
|
|
53
|
+
[tool.flit.sdist]
|
|
54
|
+
exclude = [
|
|
55
|
+
"docs/",
|
|
56
|
+
"tests/",
|
|
57
|
+
"**/.mypy_cache/",
|
|
58
|
+
"**/.ruff_cache/",
|
|
59
|
+
"**/.pytest_cache/",
|
|
60
|
+
"**/__pycache__/",
|
|
61
|
+
"**/.dmypy.json",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
[tool.pytest]
|
|
65
|
+
addopts = ["-ra"]
|
|
66
|
+
consider_namespace_packages = true
|
|
67
|
+
testpaths = ["tests/"]
|
|
68
|
+
|
|
47
69
|
[tool.mypy]
|
|
48
|
-
enable_incomplete_feature = "NewGenericSyntax"
|
|
49
70
|
explicit_package_bases = true
|
|
50
|
-
implicit_reexport = false
|
|
51
71
|
local_partial_types = true
|
|
52
72
|
namespace_packages = true
|
|
53
73
|
warn_redundant_casts = true
|
|
54
74
|
warn_return_any = true
|
|
55
75
|
warn_unused_configs = true
|
|
56
76
|
|
|
57
|
-
[tool.pylsp-mypy]
|
|
58
|
-
enabled = true
|
|
59
|
-
live-mode = true
|
|
60
|
-
dmypy = false
|
|
61
|
-
strict = true
|
|
62
|
-
report_progress = true
|
|
63
|
-
|
|
64
|
-
[tool.pytest.ini_options]
|
|
65
|
-
addopts = "-ra"
|
|
66
|
-
consider_namespace_packages = true
|
|
67
|
-
testpaths = ["tests/"]
|
|
68
|
-
|
|
69
77
|
[tool.ruff]
|
|
70
|
-
target-version = "
|
|
78
|
+
target-version = "py314"
|
|
79
|
+
|
|
80
|
+
[tool.ruff.lint]
|
|
81
|
+
ignore = ["RUF022", "E741"]
|
|
71
82
|
|
|
72
83
|
[tool.ruff.lint.flake8-quotes]
|
|
73
84
|
docstring-quotes = "double"
|
|
74
85
|
|
|
75
86
|
[tool.ruff.lint.per-file-ignores]
|
|
76
|
-
"tests
|
|
77
|
-
"
|
|
87
|
+
"tests/**/*.py" = [
|
|
88
|
+
"E731",
|
|
89
|
+
"C901",
|
|
90
|
+
]
|
|
78
91
|
|
|
79
92
|
[tool.ruff.format]
|
|
80
93
|
quote-style = "single"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2024-
|
|
1
|
+
# Copyright 2024-2026 Geoffrey R. Scheller
|
|
2
2
|
#
|
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
# you may not use this file except in compliance with the License.
|
|
@@ -13,19 +13,14 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
"""
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
NumPy Tools
|
|
17
|
+
-----------
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
.. admonition:: Functional Tools for Numpy
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
-------
|
|
21
|
+
Package implementing functional programming tools for NumPy.
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
| Module | Description |
|
|
26
|
-
+===============================+======================================+
|
|
27
|
-
| **hashable_wrapped_ndarray** | Make non-writable NDArrays hashable. |
|
|
28
|
-
+-------------------------------+--------------------------------------+
|
|
23
|
+
- module **hashable_wrapped_ndarray:** Wrap a non-writable NDArray making result hashable.
|
|
29
24
|
|
|
30
25
|
"""
|
|
31
26
|
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
# Copyright 2025-2026 Geoffrey R. Scheller
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from abc import ABC, abstractmethod
|
|
16
|
+
from enum import auto, Enum
|
|
17
|
+
import numpy as np
|
|
18
|
+
import numpy.typing as npt
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
'DTypes',
|
|
22
|
+
'HWrapNDArray',
|
|
23
|
+
'HWrapNDArrayNumber',
|
|
24
|
+
'HWrapNDArrayString',
|
|
25
|
+
'HWrapNDArrayBytes',
|
|
26
|
+
'HWrapNDArrayVoid',
|
|
27
|
+
'HWrapNDArrayObject',
|
|
28
|
+
'HWrapNDArrayDateTime',
|
|
29
|
+
'HWrapNDArrayTimeDelta',
|
|
30
|
+
'HWrapNDArrayBool',
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class DTypes(Enum):
|
|
35
|
+
"""
|
|
36
|
+
.. admonition:: Enumeration of closed NumPy datatypes
|
|
37
|
+
|
|
38
|
+
Groups (Unions) of NumPy datatypes closed to NumPy operations.
|
|
39
|
+
|
|
40
|
+
- number
|
|
41
|
+
- str\\_
|
|
42
|
+
- bytes
|
|
43
|
+
- datetime64
|
|
44
|
+
- timedelta64
|
|
45
|
+
- bool\\_
|
|
46
|
+
- void
|
|
47
|
+
- object\\_
|
|
48
|
+
|
|
49
|
+
While NumPy types are extensively covariant, the NumPy
|
|
50
|
+
C internals are somewhat invariant. NumPy also suffers
|
|
51
|
+
from what I call "Fortran Disease", types get "auto-promoted"
|
|
52
|
+
to compatible "wider types" when necessary. That is fine when
|
|
53
|
+
dealing with operators on mixed types, but NumPy will
|
|
54
|
+
auto-promote with operations on the same type.
|
|
55
|
+
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
number = auto()
|
|
59
|
+
str_ = auto()
|
|
60
|
+
bytes = auto()
|
|
61
|
+
void = auto()
|
|
62
|
+
object_ = auto()
|
|
63
|
+
datetime64 = auto()
|
|
64
|
+
timedelta64 = auto()
|
|
65
|
+
bool_ = auto()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class HWrapNDArray(ABC):
|
|
69
|
+
"""
|
|
70
|
+
Make NumPy NDArrays hashable.
|
|
71
|
+
|
|
72
|
+
Just making an NDArray (np.array) readonly is not enough. This class
|
|
73
|
+
stores a read-only copy of the NDArray given to the constructor and
|
|
74
|
+
is hashable.
|
|
75
|
+
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
__slots__ = '_ndarray', '_type', '_shape', '_hash'
|
|
79
|
+
|
|
80
|
+
def __init__(self, ndarray: npt.NDArray[np.generic]) -> None:
|
|
81
|
+
"""
|
|
82
|
+
.. admonition:: init
|
|
83
|
+
|
|
84
|
+
Base class for a hashable wrapped ndarray.
|
|
85
|
+
|
|
86
|
+
"""
|
|
87
|
+
self._ndarray = np.array(ndarray, copy=True)
|
|
88
|
+
self._ndarray.setflags(write=False)
|
|
89
|
+
|
|
90
|
+
dtype = self._ndarray.dtype.type
|
|
91
|
+
if issubclass(dtype, np.number):
|
|
92
|
+
self._type = DTypes.number
|
|
93
|
+
elif isinstance(dtype, np.str_):
|
|
94
|
+
self._type = DTypes.str_
|
|
95
|
+
elif issubclass(dtype, np.bytes_):
|
|
96
|
+
self._type = DTypes.bytes
|
|
97
|
+
elif issubclass(dtype, np.datetime64):
|
|
98
|
+
self._type = DTypes.datetime64
|
|
99
|
+
elif issubclass(dtype, np.timedelta64):
|
|
100
|
+
self._type = DTypes.timedelta64
|
|
101
|
+
elif issubclass(dtype, np.bool_):
|
|
102
|
+
self._type = DTypes.bool_
|
|
103
|
+
elif issubclass(dtype, np.void):
|
|
104
|
+
self._type = DTypes.void
|
|
105
|
+
elif issubclass(dtype, np.object_):
|
|
106
|
+
self._type = DTypes.object_
|
|
107
|
+
else:
|
|
108
|
+
msg = f"HWrapNDArray: Unknow np.dtype '{dtype}'"
|
|
109
|
+
raise TypeError(msg)
|
|
110
|
+
|
|
111
|
+
self._shape = self._ndarray.shape
|
|
112
|
+
self._hash = hash((self._ndarray.tobytes(), hash((self._shape, self._type))))
|
|
113
|
+
|
|
114
|
+
def __call__(self) -> npt.NDArray[np.number]:
|
|
115
|
+
"""
|
|
116
|
+
.. admonition:: call
|
|
117
|
+
|
|
118
|
+
Return a reference to the stored NDArray.
|
|
119
|
+
|
|
120
|
+
.. warning::
|
|
121
|
+
|
|
122
|
+
For efficiency this method returns a reference to the
|
|
123
|
+
wrapped NDArray, not a copy.
|
|
124
|
+
|
|
125
|
+
- Allows for faster slicing and faster operations.
|
|
126
|
+
- Use the copy method if you want a read-write copy.
|
|
127
|
+
- Never make the underlying NDArray writable!!!
|
|
128
|
+
|
|
129
|
+
"""
|
|
130
|
+
return np.array(self._ndarray)
|
|
131
|
+
|
|
132
|
+
def __hash__(self) -> int:
|
|
133
|
+
"""
|
|
134
|
+
.. admonition:: hash
|
|
135
|
+
|
|
136
|
+
Return hash created during initialization. Hash only
|
|
137
|
+
remains valid if NDArray's flag remains off.
|
|
138
|
+
|
|
139
|
+
"""
|
|
140
|
+
return self._hash
|
|
141
|
+
|
|
142
|
+
def __eq__(self, other: object) -> bool:
|
|
143
|
+
"""
|
|
144
|
+
.. admonition:: equality comparison
|
|
145
|
+
|
|
146
|
+
:param other: The ``object`` being compared to ``self``.
|
|
147
|
+
:returns: ``True`` if ``object`` is another ``HWrapNDArray``
|
|
148
|
+
all whose corresponding components are equal to
|
|
149
|
+
the ones in ``self``.
|
|
150
|
+
|
|
151
|
+
"""
|
|
152
|
+
if not isinstance(other, type(self)):
|
|
153
|
+
return False
|
|
154
|
+
if self._shape != other._shape or self._type != other._type:
|
|
155
|
+
return False
|
|
156
|
+
return np.array_equal(self._ndarray, other._ndarray)
|
|
157
|
+
|
|
158
|
+
def _ndarray_repr(self) -> str:
|
|
159
|
+
ndarray = self._ndarray
|
|
160
|
+
repr_str = repr(ndarray)
|
|
161
|
+
repr_str = 'np.' + repr_str.replace('\n', '')
|
|
162
|
+
repr_str = repr_str.replace(' ', '')
|
|
163
|
+
repr_str = repr_str.replace('=', "=np.")
|
|
164
|
+
return repr_str
|
|
165
|
+
|
|
166
|
+
@abstractmethod
|
|
167
|
+
def __repr__(self) -> str: ...
|
|
168
|
+
|
|
169
|
+
def __str__(self) -> str:
|
|
170
|
+
"""
|
|
171
|
+
.. admonition:: user string
|
|
172
|
+
|
|
173
|
+
:returns: String meaningful to an end user.
|
|
174
|
+
|
|
175
|
+
"""
|
|
176
|
+
user_str = str(self._ndarray)
|
|
177
|
+
user_str = user_str.replace('\n ', '\n ')
|
|
178
|
+
user_str = '<< ' + user_str + ' >>'
|
|
179
|
+
return user_str
|
|
180
|
+
|
|
181
|
+
def copy(self) -> npt.NDArray[np.number]:
|
|
182
|
+
"""
|
|
183
|
+
.. admonition:: copy
|
|
184
|
+
|
|
185
|
+
Return a copy of the wrapped NDArray.
|
|
186
|
+
|
|
187
|
+
"""
|
|
188
|
+
return np.array(self._ndarray, copy=True)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
class HWrapNDArrayNumber(HWrapNDArray):
|
|
192
|
+
"""
|
|
193
|
+
.. admonition:: wrapped numeric ndarray
|
|
194
|
+
|
|
195
|
+
Class for a hashable wrapped numeric ndarray.
|
|
196
|
+
|
|
197
|
+
"""
|
|
198
|
+
def __init__(self, ndarray: npt.NDArray[np.number]) -> None:
|
|
199
|
+
"""
|
|
200
|
+
.. admonition:: init
|
|
201
|
+
|
|
202
|
+
Wrap NDArray of arbitrary NumPy numeric types.
|
|
203
|
+
|
|
204
|
+
"""
|
|
205
|
+
super().__init__(ndarray)
|
|
206
|
+
|
|
207
|
+
def __repr__(self) -> str:
|
|
208
|
+
"""
|
|
209
|
+
.. admonition:: repr string
|
|
210
|
+
|
|
211
|
+
:returns: String to reproduce the wrapped numeric ndarray.
|
|
212
|
+
|
|
213
|
+
"""
|
|
214
|
+
return 'HWrapNDArrayNumber(' + self._ndarray_repr() + ')'
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
class HWrapNDArrayString(HWrapNDArray):
|
|
218
|
+
"""
|
|
219
|
+
.. admonition:: wrapped string ndarray
|
|
220
|
+
|
|
221
|
+
Class for a hashable wrapped string ndarray.
|
|
222
|
+
|
|
223
|
+
"""
|
|
224
|
+
def __init__(self, ndarray: npt.NDArray[np.str_]) -> None:
|
|
225
|
+
"""
|
|
226
|
+
.. admonition:: init
|
|
227
|
+
|
|
228
|
+
Wrap NDArray of Unicode strings.
|
|
229
|
+
|
|
230
|
+
"""
|
|
231
|
+
super().__init__(ndarray)
|
|
232
|
+
|
|
233
|
+
def __repr__(self) -> str:
|
|
234
|
+
"""
|
|
235
|
+
.. admonition:: repr string
|
|
236
|
+
|
|
237
|
+
:returns: String to reproduce the wrapped string ndarray.
|
|
238
|
+
|
|
239
|
+
"""
|
|
240
|
+
return 'HWrapNDArrayStr(' + self._ndarray_repr() + ')'
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
class HWrapNDArrayBytes(HWrapNDArray):
|
|
244
|
+
"""
|
|
245
|
+
.. admonition:: wrapped byte ndarray
|
|
246
|
+
|
|
247
|
+
Class for a hashable wrapped null-terminated
|
|
248
|
+
byte sequence ndarray.
|
|
249
|
+
|
|
250
|
+
"""
|
|
251
|
+
def __init__(self, ndarray: npt.NDArray[np.bytes_]) -> None:
|
|
252
|
+
"""
|
|
253
|
+
.. admonition:: init
|
|
254
|
+
|
|
255
|
+
Wrap NDArray of null-terminated byte sequences.
|
|
256
|
+
|
|
257
|
+
"""
|
|
258
|
+
super().__init__(ndarray)
|
|
259
|
+
|
|
260
|
+
def __repr__(self) -> str:
|
|
261
|
+
"""
|
|
262
|
+
.. admonition:: repr string
|
|
263
|
+
|
|
264
|
+
:returns: String to reproduce the wrapped null-terminated
|
|
265
|
+
byte sequence ndarray.
|
|
266
|
+
|
|
267
|
+
"""
|
|
268
|
+
return 'HWrapNDArrayBytes(' + self._ndarray_repr() + ')'
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
class HWrapNDArrayVoid(HWrapNDArray):
|
|
272
|
+
"""
|
|
273
|
+
.. admonition:: wrapped void ndarray
|
|
274
|
+
|
|
275
|
+
Class for a hashable wrapped arbitrary byte
|
|
276
|
+
sequence ndarray.
|
|
277
|
+
|
|
278
|
+
"""
|
|
279
|
+
def __init__(self, ndarray: npt.NDArray[np.void]) -> None:
|
|
280
|
+
"""
|
|
281
|
+
.. admonition:: init
|
|
282
|
+
|
|
283
|
+
Wrap NDArray of arbitrary byte sequences.
|
|
284
|
+
|
|
285
|
+
"""
|
|
286
|
+
super().__init__(ndarray)
|
|
287
|
+
|
|
288
|
+
def __repr__(self) -> str:
|
|
289
|
+
"""
|
|
290
|
+
.. admonition:: repr string
|
|
291
|
+
|
|
292
|
+
:returns: String to reproduce the wrapped arbitrary
|
|
293
|
+
byte sequence ndarray.
|
|
294
|
+
|
|
295
|
+
"""
|
|
296
|
+
return 'HWrapNDArrayVoid(' + self._ndarray_repr() + ')'
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
class HWrapNDArrayObject(HWrapNDArray):
|
|
300
|
+
"""
|
|
301
|
+
.. admonition:: wrapped object reference ndarray
|
|
302
|
+
|
|
303
|
+
Class for a hashable wrapped object reference ndarray.
|
|
304
|
+
|
|
305
|
+
"""
|
|
306
|
+
def __init__(self, ndarray: npt.NDArray[np.object_]) -> None:
|
|
307
|
+
"""
|
|
308
|
+
.. admonition:: init
|
|
309
|
+
|
|
310
|
+
Wrap NDArray of references to arbitrary Python objects.
|
|
311
|
+
|
|
312
|
+
"""
|
|
313
|
+
super().__init__(ndarray)
|
|
314
|
+
|
|
315
|
+
def __repr__(self) -> str:
|
|
316
|
+
"""
|
|
317
|
+
.. admonition:: repr string
|
|
318
|
+
|
|
319
|
+
:returns: String to reproduce the wrapped object
|
|
320
|
+
reference ndarray.
|
|
321
|
+
|
|
322
|
+
"""
|
|
323
|
+
return 'HWrapNDArrayObject(' + self._ndarray_repr() + ')'
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
class HWrapNDArrayDateTime(HWrapNDArray):
|
|
327
|
+
"""
|
|
328
|
+
.. admonition:: wrapped datetime ndarray
|
|
329
|
+
|
|
330
|
+
Class for a hashable wrapped datatime ndarray.
|
|
331
|
+
|
|
332
|
+
"""
|
|
333
|
+
def __init__(self, ndarray: npt.NDArray[np.datetime64]) -> None:
|
|
334
|
+
"""
|
|
335
|
+
.. admonition:: init
|
|
336
|
+
|
|
337
|
+
Wrap NDArray of datetimes.
|
|
338
|
+
|
|
339
|
+
"""
|
|
340
|
+
super().__init__(ndarray)
|
|
341
|
+
|
|
342
|
+
def __repr__(self) -> str:
|
|
343
|
+
"""
|
|
344
|
+
.. admonition:: repr string
|
|
345
|
+
|
|
346
|
+
:returns: String to reproduce the wrapped datetime ndarray.
|
|
347
|
+
|
|
348
|
+
"""
|
|
349
|
+
return 'HWrapNDArrayTimeDelta(' + self._ndarray_repr() + ')'
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
class HWrapNDArrayTimeDelta(HWrapNDArray):
|
|
353
|
+
"""
|
|
354
|
+
.. admonition:: wrapped timedelta ndarray
|
|
355
|
+
|
|
356
|
+
Class for a hashable wrapped timedelta ndarray.
|
|
357
|
+
|
|
358
|
+
"""
|
|
359
|
+
def __init__(self, ndarray: npt.NDArray[np.timedelta64]) -> None:
|
|
360
|
+
"""
|
|
361
|
+
.. admonition:: init
|
|
362
|
+
|
|
363
|
+
Wrap NDArray of timedeltas.
|
|
364
|
+
|
|
365
|
+
"""
|
|
366
|
+
super().__init__(ndarray)
|
|
367
|
+
|
|
368
|
+
def __repr__(self) -> str:
|
|
369
|
+
"""
|
|
370
|
+
.. admonition:: repr string
|
|
371
|
+
|
|
372
|
+
:returns: String to reproduce the wrapped timedelta ndarray.
|
|
373
|
+
|
|
374
|
+
"""
|
|
375
|
+
return 'HWrapNDArrayTimeDelta(' + self._ndarray_repr() + ')'
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
class HWrapNDArrayBool(HWrapNDArray):
|
|
379
|
+
"""
|
|
380
|
+
.. admonition:: wrapped Boolean ndarray
|
|
381
|
+
|
|
382
|
+
Class for a hashable wrapped Boolean ndarray.
|
|
383
|
+
|
|
384
|
+
.. note::
|
|
385
|
+
|
|
386
|
+
NumPy Booleans are actual Booleans, unlike Python bools
|
|
387
|
+
which are subtypes of int.
|
|
388
|
+
|
|
389
|
+
- ``*`` uses component-wise Boolean **and**
|
|
390
|
+
- ``+`` uses component-wise Boolean **or**
|
|
391
|
+
- ``@`` matrix multiplication using **and** then **or**
|
|
392
|
+
|
|
393
|
+
"""
|
|
394
|
+
|
|
395
|
+
def __init__(self, ndarray: npt.NDArray[np.bool_]) -> None:
|
|
396
|
+
"""
|
|
397
|
+
.. admonition:: init
|
|
398
|
+
|
|
399
|
+
Wrap NDArray of Booleans.
|
|
400
|
+
|
|
401
|
+
"""
|
|
402
|
+
super().__init__(ndarray)
|
|
403
|
+
|
|
404
|
+
def __repr__(self) -> str:
|
|
405
|
+
"""
|
|
406
|
+
.. admonition:: repr string
|
|
407
|
+
|
|
408
|
+
:returns: String to reproduce the wrapped Boolean ndarray.
|
|
409
|
+
|
|
410
|
+
"""
|
|
411
|
+
return 'HWrapNDArrayBool(' + self._ndarray_repr() + ')'
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
CHANGELOG
|
|
2
|
-
=========
|
|
3
|
-
|
|
4
|
-
PyPI pythonic-fp-numpy project.
|
|
5
|
-
|
|
6
|
-
Semantic Versioning
|
|
7
|
-
-------------------
|
|
8
|
-
|
|
9
|
-
Strict 3 digit semantic versioning
|
|
10
|
-
|
|
11
|
-
- **MAJOR** version incremented for incompatible API changes
|
|
12
|
-
- **MINOR** version incremented for backward compatible added functionality
|
|
13
|
-
- **PATCH** version incremented for backward compatible bug fixes
|
|
14
|
-
|
|
15
|
-
See `Semantic Versioning 2.0.0 <https://semver.org>`_.
|
|
16
|
-
|
|
17
|
-
Releases and Important Milestones
|
|
18
|
-
---------------------------------
|
|
19
|
-
|
|
20
|
-
PyPI v0.1.2 - 2026-01-16
|
|
21
|
-
~~~~~~~~~~~~~~~~~~~~~~~~
|
|
22
|
-
|
|
23
|
-
Fixed some documentation rough edges. Added *.pyi stub files. Updated __repr__
|
|
24
|
-
behavior for HWrapNDArray derived classes. Eliminated spaces.
|
|
25
|
-
|
|
26
|
-
Future directions.
|
|
27
|
-
|
|
28
|
-
- define ``+``, ``*``, and ``@`` on wrapped arrays.
|
|
29
|
-
- more tests
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
PyPI v0.1.1 - 2025-12-01
|
|
33
|
-
~~~~~~~~~~~~~~~~~~~~~~~~
|
|
34
|
-
|
|
35
|
-
Fixed problem with the extra test dependencies.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
PyPI v0.1.0 - 2025-11-30
|
|
39
|
-
~~~~~~~~~~~~~~~~~~~~~~~~
|
|
40
|
-
|
|
41
|
-
Initial PyPI release.
|
|
42
|
-
|
|
43
|
-
Update - 2025-11-26
|
|
44
|
-
~~~~~~~~~~~~~~~~~~~
|
|
45
|
-
|
|
46
|
-
Created GitHub repo for this new effort.
|
|
47
|
-
|
|
48
|
-
Previously wrote a hashable wrapper for NumPy NDArray for the test suite
|
|
49
|
-
of my boring-math-abstract-algebra PyPI project.
|
|
50
|
-
|
|
51
|
-
Makes an NDArray readonly and hashable.
|
|
52
|
-
|
|
53
|
-
Will need to drop the "only requires the Python std library" requirement
|
|
54
|
-
for pythonic-fp projects.
|
pythonic_fp_numpy-0.1.2/PKG-INFO
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: pythonic-fp-numpy
|
|
3
|
-
Version: 0.1.2
|
|
4
|
-
Summary: FP NumPy Tools
|
|
5
|
-
Keywords: numpy,ndarray,hashable,wrap
|
|
6
|
-
Author-email: "Geoffrey R. Scheller" <geoffrey@scheller.com>
|
|
7
|
-
Requires-Python: >=3.13
|
|
8
|
-
Description-Content-Type: text/x-rst
|
|
9
|
-
Classifier: Development Status :: 4 - Beta
|
|
10
|
-
Classifier: Framework :: Pytest
|
|
11
|
-
Classifier: Intended Audience :: Developers
|
|
12
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
13
|
-
Classifier: Operating System :: OS Independent
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
-
Classifier: Typing :: Typed
|
|
16
|
-
License-File: LICENSE
|
|
17
|
-
Requires-Dist: numpy>=2.3.4
|
|
18
|
-
Requires-Dist: boring-math-abstract-algebra>=1.1.0 ; extra == "test"
|
|
19
|
-
Requires-Dist: pytest>=8.4.1 ; extra == "test"
|
|
20
|
-
Project-URL: Changelog, https://github.com/grscheller/pythonic-fp-numpy/blob/main/CHANGELOG.rst
|
|
21
|
-
Project-URL: Documentation, https://grscheller.github.io/pythonic-fp/numpy/development/build/html/
|
|
22
|
-
Project-URL: Homepage, https://grscheller.github.io/pythonic-fp/homepage/build/html/
|
|
23
|
-
Project-URL: Source, https://github.com/grscheller/pythonic-fp-numpy
|
|
24
|
-
Provides-Extra: test
|
|
25
|
-
|
|
26
|
-
Pythonic FP - FP NumPy
|
|
27
|
-
======================
|
|
28
|
-
|
|
29
|
-
PyPI project
|
|
30
|
-
`pythonic-fp-numpy
|
|
31
|
-
<https://pypi.org/project/pythonic-fp-numpy>`_.
|
|
32
|
-
|
|
33
|
-
Python package implementing functional programming for NumPy.
|
|
34
|
-
|
|
35
|
-
Part of the
|
|
36
|
-
`pythonic-fp
|
|
37
|
-
<https://grscheller.github.io/pythonic-fp>`_
|
|
38
|
-
PyPI projects.
|
|
39
|
-
|
|
40
|
-
Modules
|
|
41
|
-
-------
|
|
42
|
-
|
|
43
|
-
Module hashable_wrapped_ndarray
|
|
44
|
-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
45
|
-
|
|
46
|
-
- wrap readonly NDArrays to make them hashable
|
|
47
|
-
- prioritize performance over safety
|
|
48
|
-
- see PyPI project boring-math-abstract-algebra for a use case
|
|
49
|
-
|
|
50
|
-
Documentation
|
|
51
|
-
-------------
|
|
52
|
-
|
|
53
|
-
Documentation for this project is hosted on
|
|
54
|
-
`GitHub Pages
|
|
55
|
-
<https://grscheller.github.io/pythonic-fp/numpy>`_.
|
|
56
|
-
|
|
57
|
-
Copyright and License
|
|
58
|
-
---------------------
|
|
59
|
-
|
|
60
|
-
Copyright (c) 2025-2026 Geoffrey R. Scheller. Licensed under the Apache
|
|
61
|
-
License, Version 2.0. See the LICENSE file for details.
|
|
62
|
-
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
Pythonic FP - FP NumPy
|
|
2
|
-
======================
|
|
3
|
-
|
|
4
|
-
PyPI project
|
|
5
|
-
`pythonic-fp-numpy
|
|
6
|
-
<https://pypi.org/project/pythonic-fp-numpy>`_.
|
|
7
|
-
|
|
8
|
-
Python package implementing functional programming for NumPy.
|
|
9
|
-
|
|
10
|
-
Part of the
|
|
11
|
-
`pythonic-fp
|
|
12
|
-
<https://grscheller.github.io/pythonic-fp>`_
|
|
13
|
-
PyPI projects.
|
|
14
|
-
|
|
15
|
-
Modules
|
|
16
|
-
-------
|
|
17
|
-
|
|
18
|
-
Module hashable_wrapped_ndarray
|
|
19
|
-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
20
|
-
|
|
21
|
-
- wrap readonly NDArrays to make them hashable
|
|
22
|
-
- prioritize performance over safety
|
|
23
|
-
- see PyPI project boring-math-abstract-algebra for a use case
|
|
24
|
-
|
|
25
|
-
Documentation
|
|
26
|
-
-------------
|
|
27
|
-
|
|
28
|
-
Documentation for this project is hosted on
|
|
29
|
-
`GitHub Pages
|
|
30
|
-
<https://grscheller.github.io/pythonic-fp/numpy>`_.
|
|
31
|
-
|
|
32
|
-
Copyright and License
|
|
33
|
-
---------------------
|
|
34
|
-
|
|
35
|
-
Copyright (c) 2025-2026 Geoffrey R. Scheller. Licensed under the Apache
|
|
36
|
-
License, Version 2.0. See the LICENSE file for details.
|
|
File without changes
|
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
# Copyright 2025-2026 Geoffrey R. Scheller
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
|
|
15
|
-
from abc import ABC, abstractmethod
|
|
16
|
-
from enum import auto, Enum
|
|
17
|
-
import numpy as np
|
|
18
|
-
import numpy.typing as npt
|
|
19
|
-
|
|
20
|
-
__all__ = [
|
|
21
|
-
'DTypes',
|
|
22
|
-
'HWrapNDArray',
|
|
23
|
-
'HWrapNDArrayNumber',
|
|
24
|
-
'HWrapNDArrayString',
|
|
25
|
-
'HWrapNDArrayBytes',
|
|
26
|
-
'HWrapNDArrayVoid',
|
|
27
|
-
'HWrapNDArrayObject',
|
|
28
|
-
'HWrapNDArrayDateTime',
|
|
29
|
-
'HWrapNDArrayTimeDelta',
|
|
30
|
-
'HWrapNDArrayBool',
|
|
31
|
-
]
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
class DTypes(Enum):
|
|
35
|
-
"""Enumeration of closed NumPy datatypes.
|
|
36
|
-
|
|
37
|
-
.. admonition:: Groups (Unions) of NumPy datatypes closed to NumPy operations.
|
|
38
|
-
|
|
39
|
-
- number
|
|
40
|
-
- str\_
|
|
41
|
-
- bytes
|
|
42
|
-
- datetime64
|
|
43
|
-
- timedelta64
|
|
44
|
-
- bool\_
|
|
45
|
-
- void
|
|
46
|
-
- object\_
|
|
47
|
-
|
|
48
|
-
While NumPy types are extensively covariant, the NumPy C internals
|
|
49
|
-
are somewhat invariant. NumPy also suffers from what I call "Fortran
|
|
50
|
-
Disease", types get "auto-promoted" to compatible "wider types" when
|
|
51
|
-
necessary. That is fine when dealing with operators on mixed types,
|
|
52
|
-
but NumPy will auto-promote with operations on the same type.
|
|
53
|
-
|
|
54
|
-
"""
|
|
55
|
-
|
|
56
|
-
number = auto()
|
|
57
|
-
str_ = auto()
|
|
58
|
-
bytes = auto()
|
|
59
|
-
void = auto()
|
|
60
|
-
object_ = auto()
|
|
61
|
-
datetime64 = auto()
|
|
62
|
-
timedelta64 = auto()
|
|
63
|
-
bool_ = auto()
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
class HWrapNDArray(ABC):
|
|
67
|
-
"""
|
|
68
|
-
Make NumPy NDArrays hashable.
|
|
69
|
-
|
|
70
|
-
Just making an NDArray (np.array) readonly is not enough. This class
|
|
71
|
-
stores a read-only copy of the NDArray given to the constructor and
|
|
72
|
-
is hashable.
|
|
73
|
-
|
|
74
|
-
"""
|
|
75
|
-
|
|
76
|
-
__slots__ = '_ndarray', '_type', '_shape', '_hash'
|
|
77
|
-
|
|
78
|
-
def __init__(self, ndarray: npt.NDArray[np.generic]) -> None:
|
|
79
|
-
self._ndarray = np.array(ndarray, copy=True)
|
|
80
|
-
self._ndarray.setflags(write=False)
|
|
81
|
-
|
|
82
|
-
dtype = self._ndarray.dtype.type
|
|
83
|
-
if issubclass(dtype, np.number):
|
|
84
|
-
self._type = DTypes.number
|
|
85
|
-
elif isinstance(dtype, np.str_):
|
|
86
|
-
self._type = DTypes.str_
|
|
87
|
-
elif issubclass(dtype, np.bytes_):
|
|
88
|
-
self._type = DTypes.bytes
|
|
89
|
-
elif issubclass(dtype, np.datetime64):
|
|
90
|
-
self._type = DTypes.datetime64
|
|
91
|
-
elif issubclass(dtype, np.timedelta64):
|
|
92
|
-
self._type = DTypes.timedelta64
|
|
93
|
-
elif issubclass(dtype, np.bool_):
|
|
94
|
-
self._type = DTypes.bool_
|
|
95
|
-
elif issubclass(dtype, np.void):
|
|
96
|
-
self._type = DTypes.void
|
|
97
|
-
elif issubclass(dtype, np.object_):
|
|
98
|
-
self._type = DTypes.object_
|
|
99
|
-
else:
|
|
100
|
-
msg = f"HWrapNDArray: Unknow np.dtype '{dtype}'"
|
|
101
|
-
raise TypeError(msg)
|
|
102
|
-
|
|
103
|
-
self._shape = self._ndarray.shape
|
|
104
|
-
self._hash = hash((self._ndarray.tobytes(), hash((self._shape, self._type))))
|
|
105
|
-
|
|
106
|
-
@abstractmethod
|
|
107
|
-
def __repr__(self) -> str: ...
|
|
108
|
-
|
|
109
|
-
def __call__(self) -> npt.NDArray[np.number]:
|
|
110
|
-
"""Return a reference to the stored NDArray.
|
|
111
|
-
|
|
112
|
-
.. warning::
|
|
113
|
-
|
|
114
|
-
For efficiency this method returns a reference to the
|
|
115
|
-
wrapped NDArray.
|
|
116
|
-
|
|
117
|
-
- Allows for faster slicing and faster operations.
|
|
118
|
-
- Use the copy method if you want a read-write copy.
|
|
119
|
-
- Never make the underlying NDArray writable!!!
|
|
120
|
-
|
|
121
|
-
"""
|
|
122
|
-
return np.array(self._ndarray)
|
|
123
|
-
|
|
124
|
-
def __hash__(self) -> int:
|
|
125
|
-
return self._hash
|
|
126
|
-
|
|
127
|
-
def __eq__(self, other: object) -> bool:
|
|
128
|
-
if not isinstance(other, HWrapNDArray):
|
|
129
|
-
return False
|
|
130
|
-
if self._shape != other._shape or self._type != other._type:
|
|
131
|
-
return False
|
|
132
|
-
return np.array_equal(self._ndarray, other._ndarray)
|
|
133
|
-
|
|
134
|
-
def __str__(self) -> str:
|
|
135
|
-
np_array_str = ' ' + str(self._ndarray).replace('\n', '\n ')
|
|
136
|
-
return f'hwrap<\n{np_array_str}\n>'
|
|
137
|
-
|
|
138
|
-
def _repr(self) -> str:
|
|
139
|
-
stripped_repr = ''.join(repr(self._ndarray).split())
|
|
140
|
-
return f'np.{stripped_repr}'
|
|
141
|
-
|
|
142
|
-
def copy(self) -> npt.NDArray[np.number]:
|
|
143
|
-
"""Return a copy of the wrapped NDArray."""
|
|
144
|
-
return np.array(self._ndarray, copy=True)
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
class HWrapNDArrayNumber(HWrapNDArray):
|
|
148
|
-
"""Wrap NDArrays of arbitrary NumPy numeric types."""
|
|
149
|
-
|
|
150
|
-
def __init__(self, ndarray: npt.NDArray[np.number]) -> None:
|
|
151
|
-
super().__init__(ndarray)
|
|
152
|
-
|
|
153
|
-
def __repr__(self) -> str:
|
|
154
|
-
return f'HWrapNDArrayNumber({self._repr()})'
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
class HWrapNDArrayString(HWrapNDArray):
|
|
158
|
-
"""Wrap NDArrays of Unicode strings."""
|
|
159
|
-
|
|
160
|
-
def __init__(self, ndarray: npt.NDArray[np.str_]) -> None:
|
|
161
|
-
super().__init__(ndarray)
|
|
162
|
-
|
|
163
|
-
def __repr__(self) -> str:
|
|
164
|
-
return f'HWrapNDArrayStr({self._repr()})'
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
class HWrapNDArrayBytes(HWrapNDArray):
|
|
168
|
-
"""Wrap NDArrays of null-terminated byte sequences."""
|
|
169
|
-
|
|
170
|
-
def __init__(self, ndarray: npt.NDArray[np.bytes_]) -> None:
|
|
171
|
-
super().__init__(ndarray)
|
|
172
|
-
|
|
173
|
-
def __repr__(self) -> str:
|
|
174
|
-
return f'HWrapNDArrayBytes({self._repr()})'
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
class HWrapNDArrayDateTime(HWrapNDArray):
|
|
178
|
-
"""Wrap NDArrays of references to arbitrary Python objects."""
|
|
179
|
-
|
|
180
|
-
def __init__(self, ndarray: npt.NDArray[np.datetime64]) -> None:
|
|
181
|
-
super().__init__(ndarray)
|
|
182
|
-
|
|
183
|
-
def __repr__(self) -> str:
|
|
184
|
-
return f'HWrapNDArrayTimeDelta({self._repr()})'
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
class HWrapNDArrayTimeDelta(HWrapNDArray):
|
|
188
|
-
"""Wrap NDArrays of references to arbitrary Python objects."""
|
|
189
|
-
|
|
190
|
-
def __init__(self, ndarray: npt.NDArray[np.timedelta64]) -> None:
|
|
191
|
-
super().__init__(ndarray)
|
|
192
|
-
|
|
193
|
-
def __repr__(self) -> str:
|
|
194
|
-
return f'HWrapNDArrayTimeDelta({self._repr()})'
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
class HWrapNDArrayVoid(HWrapNDArray):
|
|
198
|
-
"""Wrap NDArrays of arbitrary byte sequences."""
|
|
199
|
-
|
|
200
|
-
def __init__(self, ndarray: npt.NDArray[np.void]) -> None:
|
|
201
|
-
super().__init__(ndarray)
|
|
202
|
-
|
|
203
|
-
def __repr__(self) -> str:
|
|
204
|
-
return f'HWrapNDArrayVoid({self._repr()})'
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
class HWrapNDArrayObject(HWrapNDArray):
|
|
208
|
-
"""Wrap NDArrays of references to arbitrary Python objects."""
|
|
209
|
-
|
|
210
|
-
def __init__(self, ndarray: npt.NDArray[np.object_]) -> None:
|
|
211
|
-
super().__init__(ndarray)
|
|
212
|
-
|
|
213
|
-
def __repr__(self) -> str:
|
|
214
|
-
return f'HWrapNDArrayObject({self._repr()})'
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
class HWrapNDArrayBool(HWrapNDArray):
|
|
218
|
-
"""Wrap NDArrays of Booleans.
|
|
219
|
-
|
|
220
|
-
NumPy Booleans are actual Booleans, unlike Python bools which are
|
|
221
|
-
subtypes of int.
|
|
222
|
-
|
|
223
|
-
.. note::
|
|
224
|
-
|
|
225
|
-
- ``*`` uses component-wise Boolean **and**
|
|
226
|
-
- ``+`` uses component-wise Boolean **or**
|
|
227
|
-
- ``@`` does matrix multiplication using **and** then **or**
|
|
228
|
-
|
|
229
|
-
"""
|
|
230
|
-
|
|
231
|
-
def __init__(self, ndarray: npt.NDArray[np.bool_]) -> None:
|
|
232
|
-
super().__init__(ndarray)
|
|
233
|
-
|
|
234
|
-
def __repr__(self) -> str:
|
|
235
|
-
return f'HWrapNDArrayBool({self._repr()})'
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import abc
|
|
2
|
-
import numpy as np
|
|
3
|
-
import numpy.typing as npt
|
|
4
|
-
from abc import ABC
|
|
5
|
-
from enum import Enum
|
|
6
|
-
|
|
7
|
-
__all__ = ['DTypes', 'HWrapNDArray', 'HWrapNDArrayNumber', 'HWrapNDArrayString', 'HWrapNDArrayBytes', 'HWrapNDArrayVoid', 'HWrapNDArrayObject', 'HWrapNDArrayDateTime', 'HWrapNDArrayTimeDelta', 'HWrapNDArrayBool']
|
|
8
|
-
|
|
9
|
-
class DTypes(Enum):
|
|
10
|
-
number = ...
|
|
11
|
-
str_ = ...
|
|
12
|
-
bytes = ...
|
|
13
|
-
void = ...
|
|
14
|
-
object_ = ...
|
|
15
|
-
datetime64 = ...
|
|
16
|
-
timedelta64 = ...
|
|
17
|
-
bool_ = ...
|
|
18
|
-
|
|
19
|
-
class HWrapNDArray(ABC, metaclass=abc.ABCMeta):
|
|
20
|
-
def __init__(self, ndarray: npt.NDArray[np.generic]) -> None: ...
|
|
21
|
-
def __call__(self) -> npt.NDArray[np.number]: ...
|
|
22
|
-
def __hash__(self) -> int: ...
|
|
23
|
-
def __eq__(self, other: object) -> bool: ...
|
|
24
|
-
def copy(self) -> npt.NDArray[np.number]: ...
|
|
25
|
-
|
|
26
|
-
class HWrapNDArrayNumber(HWrapNDArray):
|
|
27
|
-
def __init__(self, ndarray: npt.NDArray[np.number]) -> None: ...
|
|
28
|
-
|
|
29
|
-
class HWrapNDArrayString(HWrapNDArray):
|
|
30
|
-
def __init__(self, ndarray: npt.NDArray[np.str_]) -> None: ...
|
|
31
|
-
|
|
32
|
-
class HWrapNDArrayBytes(HWrapNDArray):
|
|
33
|
-
def __init__(self, ndarray: npt.NDArray[np.bytes_]) -> None: ...
|
|
34
|
-
|
|
35
|
-
class HWrapNDArrayVoid(HWrapNDArray):
|
|
36
|
-
def __init__(self, ndarray: npt.NDArray[np.void]) -> None: ...
|
|
37
|
-
|
|
38
|
-
class HWrapNDArrayObject(HWrapNDArray):
|
|
39
|
-
def __init__(self, ndarray: npt.NDArray[np.object_]) -> None: ...
|
|
40
|
-
|
|
41
|
-
class HWrapNDArrayDateTime(HWrapNDArray):
|
|
42
|
-
def __init__(self, ndarray: npt.NDArray[np.datetime64]) -> None: ...
|
|
43
|
-
|
|
44
|
-
class HWrapNDArrayTimeDelta(HWrapNDArray):
|
|
45
|
-
def __init__(self, ndarray: npt.NDArray[np.timedelta64]) -> None: ...
|
|
46
|
-
|
|
47
|
-
class HWrapNDArrayBool(HWrapNDArray):
|
|
48
|
-
def __init__(self, ndarray: npt.NDArray[np.bool_]) -> None: ...
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
# Copyright 2025 Geoffrey R. Scheller
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
|
|
15
|
-
import numpy as np
|
|
16
|
-
import numpy.typing as npt
|
|
17
|
-
from boring_math.abstract_algebra.algebras.semigroup import Semigroup
|
|
18
|
-
from pythonic_fp.numpy.hashable_wrapped_ndarray import HWrapNDArrayNumber
|
|
19
|
-
|
|
20
|
-
type I32_2x2 = HWrapNDArrayNumber[npt.NDArray[np.int32]]
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def matrix_mult(left: I32_2x2, right: I32_2x2) -> I32_2x2:
|
|
24
|
-
return HWrapNDArrayNumber(left() @ right())
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
m2x2 = Semigroup[I32_2x2](mult=matrix_mult)
|
|
28
|
-
|
|
29
|
-
np_eye = HWrapNDArrayNumber(np.eye(2, dtype=np.int32))
|
|
30
|
-
np_zero = HWrapNDArrayNumber(np.zeros((2, 2), dtype=np.int32))
|
|
31
|
-
np_A = HWrapNDArrayNumber(np.array([[5, -1], [0, 2]], dtype=np.int32))
|
|
32
|
-
np_B = HWrapNDArrayNumber(np.array([[2, -1], [-1, 2]], dtype=np.int32))
|
|
33
|
-
np_C = HWrapNDArrayNumber(np.array([[1, 1], [1, 1]], dtype=np.int32))
|
|
34
|
-
np_D = HWrapNDArrayNumber(np.array([[0, 1], [1, 0]], dtype=np.int32))
|
|
35
|
-
np_E = HWrapNDArrayNumber(np.array([[11, -7], [-2, 4]], dtype=np.int32))
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
Eye = m2x2(np_eye)
|
|
39
|
-
Zero = m2x2(np_zero)
|
|
40
|
-
A = m2x2(np_A)
|
|
41
|
-
B = m2x2(np_B)
|
|
42
|
-
C = m2x2(np_C)
|
|
43
|
-
D = m2x2(np_D)
|
|
44
|
-
E = m2x2(np_E)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
class Test_number_with_int32:
|
|
48
|
-
def test_equality(self) -> None:
|
|
49
|
-
assert Eye * Eye == Eye
|
|
50
|
-
assert Eye * A == A
|
|
51
|
-
assert B * Eye == B
|
|
52
|
-
assert E * Zero == Zero
|
|
53
|
-
assert Zero * E == Zero
|
|
54
|
-
assert (A * B) * C == A * (B * C)
|
|
55
|
-
assert D * D == Eye
|
|
56
|
-
assert A * B == E
|
|
57
|
-
|
|
58
|
-
def test_identity(self) -> None:
|
|
59
|
-
assert Eye * Eye is Eye
|
|
60
|
-
assert Eye * A is A
|
|
61
|
-
assert B * Eye is B
|
|
62
|
-
assert E * Zero is Zero
|
|
63
|
-
assert Zero * E is Zero
|
|
64
|
-
assert (A * B) * C is A * (B * C)
|
|
65
|
-
assert D * D is Eye
|
|
66
|
-
assert A * B is E
|
|
67
|
-
|
|
68
|
-
def test_pow(self) -> None:
|
|
69
|
-
Eye**5 == Eye
|
|
70
|
-
Eye**5 is Eye
|
|
71
|
-
|
|
72
|
-
def test_str(self) -> None:
|
|
73
|
-
assert str(A()) == 'hwrap<\n [[ 5 -1]\n [ 0 2]]\n>'
|
|
74
|
-
|
|
75
|
-
def test_repr(self) -> None:
|
|
76
|
-
assert repr(np_eye) == 'HWrapNDArrayNumber(np.array([[1,0],[0,1]],dtype=int32))'
|
|
77
|
-
assert repr(np_A) == 'HWrapNDArrayNumber(np.array([[5,-1],[0,2]],dtype=int32))'
|
|
78
|
-
assert repr(np_B) == 'HWrapNDArrayNumber(np.array([[2,-1],[-1,2]],dtype=int32))'
|
|
79
|
-
assert repr(HWrapNDArrayNumber(np_A() @ np_B())) == 'HWrapNDArrayNumber(np.array([[11,-7],[-2,4]],dtype=int32))'
|
|
80
|
-
|
|
81
|
-
def test_create(self) -> None:
|
|
82
|
-
np_see = HWrapNDArrayNumber(np.array([[1, 1], [1, 1]], dtype=np.int32))
|
|
83
|
-
See = m2x2(np_see)
|
|
84
|
-
assert See == C
|
|
85
|
-
assert See is C
|
|
86
|
-
assert repr(np_see) == 'HWrapNDArrayNumber(np.array([[1,1],[1,1]],dtype=int32))'
|
|
File without changes
|
|
File without changes
|