python-graphblas 2023.10.0__tar.gz → 2024.2.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.
Files changed (118) hide show
  1. {python-graphblas-2023.10.0/python_graphblas.egg-info → python-graphblas-2024.2.0}/PKG-INFO +9 -9
  2. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/README.md +1 -1
  3. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/__init__.py +5 -0
  4. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/agg/__init__.py +2 -1
  5. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/binary/numpy.py +1 -0
  6. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/automethods.py +1 -5
  7. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/base.py +12 -4
  8. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/dtypes.py +1 -2
  9. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/expr.py +4 -4
  10. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/infix.py +141 -54
  11. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/matrix.py +238 -145
  12. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/operator/__init__.py +1 -0
  13. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/operator/base.py +5 -2
  14. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/operator/binary.py +5 -1
  15. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/operator/indexunary.py +2 -0
  16. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/operator/monoid.py +6 -22
  17. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/operator/select.py +2 -0
  18. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/operator/semiring.py +2 -0
  19. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/operator/unary.py +2 -0
  20. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/operator/utils.py +29 -0
  21. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/scalar.py +83 -9
  22. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/ss/binary.py +1 -0
  23. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/ss/descriptor.py +1 -0
  24. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/ss/indexunary.py +1 -0
  25. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/ss/matrix.py +53 -60
  26. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/ss/select.py +1 -0
  27. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/ss/unary.py +1 -0
  28. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/ss/vector.py +28 -28
  29. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/utils.py +3 -1
  30. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/vector.py +199 -104
  31. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/io/__init__.py +0 -1
  32. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/io/_awkward.py +1 -0
  33. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/io/_matrixmarket.py +2 -0
  34. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/io/_networkx.py +2 -0
  35. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/io/_scipy.py +1 -0
  36. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/io/_sparse.py +1 -0
  37. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/monoid/numpy.py +1 -0
  38. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/select/__init__.py +4 -11
  39. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/semiring/numpy.py +1 -0
  40. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/ss/_core.py +2 -4
  41. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/conftest.py +10 -6
  42. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/test_core.py +4 -0
  43. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/test_descriptor.py +1 -2
  44. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/test_dtype.py +1 -1
  45. python-graphblas-2024.2.0/graphblas/tests/test_infix.py +781 -0
  46. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/test_io.py +0 -11
  47. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/test_matrix.py +39 -24
  48. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/test_op.py +0 -2
  49. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/test_scalar.py +3 -3
  50. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/test_vector.py +38 -20
  51. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/unary/numpy.py +1 -0
  52. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/viz.py +2 -0
  53. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/pyproject.toml +19 -13
  54. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0/python_graphblas.egg-info}/PKG-INFO +9 -9
  55. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/python_graphblas.egg-info/SOURCES.txt +0 -2
  56. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/python_graphblas.egg-info/requires.txt +6 -6
  57. python-graphblas-2023.10.0/graphblas/core/agg.py +0 -17
  58. python-graphblas-2023.10.0/graphblas/io/_numpy.py +0 -104
  59. python-graphblas-2023.10.0/graphblas/tests/test_infix.py +0 -369
  60. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/LICENSE +0 -0
  61. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/MANIFEST.in +0 -0
  62. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/conftest.py +0 -0
  63. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/agg/ss.py +0 -0
  64. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/binary/__init__.py +0 -0
  65. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/binary/ss.py +0 -0
  66. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/__init__.py +0 -0
  67. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/descriptor.py +0 -0
  68. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/formatting.py +0 -0
  69. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/infixmethods.py +0 -0
  70. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/mask.py +0 -0
  71. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/operator/agg.py +0 -0
  72. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/recorder.py +0 -0
  73. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/slice.py +0 -0
  74. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/ss/__init__.py +0 -0
  75. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/ss/config.py +0 -0
  76. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/ss/context.py +0 -0
  77. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/ss/dtypes.py +0 -0
  78. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/core/ss/prefix_scan.py +0 -0
  79. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/dtypes/__init__.py +0 -0
  80. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/dtypes/ss.py +0 -0
  81. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/exceptions.py +0 -0
  82. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/graphblas.yaml +0 -0
  83. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/indexunary/__init__.py +0 -0
  84. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/indexunary/ss.py +0 -0
  85. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/monoid/__init__.py +0 -0
  86. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/monoid/ss.py +0 -0
  87. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/op/__init__.py +0 -0
  88. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/op/numpy.py +0 -0
  89. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/op/ss.py +0 -0
  90. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/select/ss.py +0 -0
  91. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/semiring/__init__.py +0 -0
  92. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/semiring/ss.py +0 -0
  93. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/ss/__init__.py +0 -0
  94. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/__init__.py +0 -0
  95. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/pickle1-vanilla.pkl +0 -0
  96. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/pickle1.pkl +0 -0
  97. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/pickle2-vanilla.pkl +0 -0
  98. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/pickle2.pkl +0 -0
  99. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/pickle3-vanilla.pkl +0 -0
  100. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/pickle3.pkl +0 -0
  101. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/test_auto_init.py +0 -0
  102. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/test_external_init.py +0 -0
  103. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/test_formatting.py +0 -0
  104. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/test_mask.py +0 -0
  105. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/test_numpyops.py +0 -0
  106. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/test_operator_types.py +0 -0
  107. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/test_pickle.py +0 -0
  108. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/test_prefix_scan.py +0 -0
  109. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/test_recorder.py +0 -0
  110. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/test_resolving.py +0 -0
  111. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/test_ss_utils.py +0 -0
  112. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/tests/test_ssjit.py +0 -0
  113. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/unary/__init__.py +0 -0
  114. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/graphblas/unary/ss.py +0 -0
  115. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/python_graphblas.egg-info/dependency_links.txt +0 -0
  116. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/python_graphblas.egg-info/top_level.txt +0 -0
  117. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/setup.cfg +0 -0
  118. {python-graphblas-2023.10.0 → python-graphblas-2024.2.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-graphblas
3
- Version: 2023.10.0
3
+ Version: 2024.2.0
4
4
  Summary: Python library for GraphBLAS: high-performance sparse linear algebra for scalable graph analytics
5
5
  Author: Jim Kitchen, Python-graphblas contributors
6
6
  Author-email: Erik Welch <erik.n.welch@gmail.com>
@@ -234,11 +234,11 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
234
234
  Requires-Python: >=3.9
235
235
  Description-Content-Type: text/markdown
236
236
  License-File: LICENSE
237
- Requires-Dist: numpy>=1.21
237
+ Requires-Dist: numpy>=1.22
238
238
  Requires-Dist: donfig>=0.6
239
239
  Requires-Dist: pyyaml>=5.4
240
240
  Requires-Dist: suitesparse-graphblas<9,>=7.4.0.0
241
- Requires-Dist: numba>=0.55; python_version < "3.12"
241
+ Requires-Dist: numba>=0.55; python_version < "3.13"
242
242
  Provides-Extra: suitesparse
243
243
  Requires-Dist: suitesparse-graphblas<9,>=7.4.0.0; extra == "suitesparse"
244
244
  Provides-Extra: networkx
@@ -248,16 +248,16 @@ Requires-Dist: numba>=0.55; extra == "numba"
248
248
  Provides-Extra: pandas
249
249
  Requires-Dist: pandas>=1.2; extra == "pandas"
250
250
  Provides-Extra: scipy
251
- Requires-Dist: scipy>=1.8; extra == "scipy"
251
+ Requires-Dist: scipy>=1.9; extra == "scipy"
252
252
  Provides-Extra: suitesparse-udf
253
253
  Requires-Dist: python-graphblas[numba,suitesparse]; extra == "suitesparse-udf"
254
254
  Provides-Extra: repr
255
255
  Requires-Dist: python-graphblas[pandas]; extra == "repr"
256
256
  Provides-Extra: io
257
257
  Requires-Dist: python-graphblas[networkx,scipy]; extra == "io"
258
- Requires-Dist: python-graphblas[numba]; python_version < "3.12" and extra == "io"
258
+ Requires-Dist: python-graphblas[numba]; python_version < "3.13" and extra == "io"
259
259
  Requires-Dist: awkward>=1.9; extra == "io"
260
- Requires-Dist: sparse>=0.13; python_version < "3.12" and extra == "io"
260
+ Requires-Dist: sparse>=0.13; python_version < "3.13" and extra == "io"
261
261
  Requires-Dist: fast-matrix-market>=1.4.5; extra == "io"
262
262
  Provides-Extra: viz
263
263
  Requires-Dist: python-graphblas[networkx,scipy]; extra == "viz"
@@ -273,10 +273,10 @@ Requires-Dist: pytest>=6.2; extra == "test"
273
273
  Requires-Dist: tomli>=1; extra == "test"
274
274
  Provides-Extra: default
275
275
  Requires-Dist: python-graphblas[pandas,scipy,suitesparse]; extra == "default"
276
- Requires-Dist: python-graphblas[numba]; python_version < "3.12" and extra == "default"
276
+ Requires-Dist: python-graphblas[numba]; python_version < "3.13" and extra == "default"
277
277
  Provides-Extra: all
278
278
  Requires-Dist: python-graphblas[default,io,test,viz]; extra == "all"
279
- Requires-Dist: python-graphblas[datashade]; python_version < "3.12" and extra == "all"
279
+ Requires-Dist: python-graphblas[datashade]; python_version < "3.13" and extra == "all"
280
280
 
281
281
  ![Python-graphblas](https://raw.githubusercontent.com/python-graphblas/python-graphblas/main/docs/_static/img/logo-horizontal-medium-big.svg)
282
282
 
@@ -289,7 +289,7 @@ Requires-Dist: python-graphblas[datashade]; python_version < "3.12" and extra ==
289
289
  [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/python-graphblas)](https://pypi.python.org/pypi/python-graphblas/)
290
290
  [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/python-graphblas/python-graphblas/blob/main/LICENSE)
291
291
  <br>
292
- [![Tests](https://github.com/python-graphblas/python-graphblas/workflows/Tests/badge.svg?branch=main)](https://github.com/python-graphblas/python-graphblas/actions)
292
+ [![Tests](https://github.com/python-graphblas/python-graphblas/actions/workflows/test_and_build.yml/badge.svg?branch=main)](https://github.com/python-graphblas/python-graphblas/actions)
293
293
  [![Docs](https://readthedocs.org/projects/python-graphblas/badge/?version=latest)](https://python-graphblas.readthedocs.io/en/latest/)
294
294
  [![Coverage](https://codecov.io/gh/python-graphblas/python-graphblas/graph/badge.svg?token=D7HHLDPQ2Q)](https://codecov.io/gh/python-graphblas/python-graphblas)
295
295
  [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.7328791.svg)](https://doi.org/10.5281/zenodo.7328791)
@@ -9,7 +9,7 @@
9
9
  [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/python-graphblas)](https://pypi.python.org/pypi/python-graphblas/)
10
10
  [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/python-graphblas/python-graphblas/blob/main/LICENSE)
11
11
  <br>
12
- [![Tests](https://github.com/python-graphblas/python-graphblas/workflows/Tests/badge.svg?branch=main)](https://github.com/python-graphblas/python-graphblas/actions)
12
+ [![Tests](https://github.com/python-graphblas/python-graphblas/actions/workflows/test_and_build.yml/badge.svg?branch=main)](https://github.com/python-graphblas/python-graphblas/actions)
13
13
  [![Docs](https://readthedocs.org/projects/python-graphblas/badge/?version=latest)](https://python-graphblas.readthedocs.io/en/latest/)
14
14
  [![Coverage](https://codecov.io/gh/python-graphblas/python-graphblas/graph/badge.svg?token=D7HHLDPQ2Q)](https://codecov.io/gh/python-graphblas/python-graphblas)
15
15
  [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.7328791.svg)](https://doi.org/10.5281/zenodo.7328791)
@@ -39,6 +39,7 @@ del get_config
39
39
  backend = None
40
40
  _init_params = None
41
41
  _SPECIAL_ATTRS = {
42
+ "MAX_SIZE", # The maximum size of Vector and Matrix dimensions (GrB_INDEX_MAX + 1)
42
43
  "Matrix",
43
44
  "Recorder",
44
45
  "Scalar",
@@ -205,6 +206,10 @@ def _load(name):
205
206
  if name in {"Matrix", "Vector", "Scalar", "Recorder"}:
206
207
  module = _import_module(f".core.{name.lower()}", __name__)
207
208
  globals()[name] = getattr(module, name)
209
+ elif name == "MAX_SIZE":
210
+ from .core import lib
211
+
212
+ globals()[name] = lib.GrB_INDEX_MAX + 1
208
213
  else:
209
214
  # Everything else is a module
210
215
  globals()[name] = _import_module(f".{name}", __name__)
@@ -73,7 +73,8 @@ Custom recipes (specific to SuiteSparse:GraphBLAS):
73
73
  # - bxnor monoid: even bits
74
74
  # - bnor monoid: odd bits
75
75
  """
76
- # All items are dynamically added by classes in core/agg.py
76
+
77
+ # All items are dynamically added by classes in core/operator/agg.py
77
78
  # This module acts as a container of Aggregator instances
78
79
  _deprecated = {}
79
80
 
@@ -5,6 +5,7 @@ See list of numpy ufuncs supported by numpy here:
5
5
  https://numba.readthedocs.io/en/stable/reference/numpysupported.html#math-operations
6
6
 
7
7
  """
8
+
8
9
  import numpy as _np
9
10
 
10
11
  from .. import _STANDARD_OPERATOR_NAMES
@@ -7,6 +7,7 @@ To automatically create the functions, run:
7
7
  $ python -m graphblas.core.automethods
8
8
 
9
9
  """
10
+
10
11
  from .. import config
11
12
 
12
13
 
@@ -281,10 +282,6 @@ def to_edgelist(self):
281
282
  return self._get_value("to_edgelist")
282
283
 
283
284
 
284
- def to_values(self):
285
- return self._get_value("to_values")
286
-
287
-
288
285
  def value(self):
289
286
  return self._get_value("value")
290
287
 
@@ -398,7 +395,6 @@ def _main():
398
395
  "ss",
399
396
  "to_coo",
400
397
  "to_dense",
401
- "to_values",
402
398
  }
403
399
  vector = {
404
400
  "_as_matrix",
@@ -263,23 +263,31 @@ class BaseType:
263
263
  )
264
264
 
265
265
  def __or__(self, other):
266
- from .infix import _ewise_infix_expr
266
+ from .infix import _ewise_infix_expr, _ewise_mult_expr_types
267
267
 
268
+ if isinstance(other, _ewise_mult_expr_types):
269
+ raise TypeError("XXX")
268
270
  return _ewise_infix_expr(self, other, method="ewise_add", within="__or__")
269
271
 
270
272
  def __ror__(self, other):
271
- from .infix import _ewise_infix_expr
273
+ from .infix import _ewise_infix_expr, _ewise_mult_expr_types
272
274
 
275
+ if isinstance(other, _ewise_mult_expr_types):
276
+ raise TypeError("XXX")
273
277
  return _ewise_infix_expr(other, self, method="ewise_add", within="__ror__")
274
278
 
275
279
  def __and__(self, other):
276
- from .infix import _ewise_infix_expr
280
+ from .infix import _ewise_add_expr_types, _ewise_infix_expr
277
281
 
282
+ if isinstance(other, _ewise_add_expr_types):
283
+ raise TypeError("XXX")
278
284
  return _ewise_infix_expr(self, other, method="ewise_mult", within="__and__")
279
285
 
280
286
  def __rand__(self, other):
281
- from .infix import _ewise_infix_expr
287
+ from .infix import _ewise_add_expr_types, _ewise_infix_expr
282
288
 
289
+ if isinstance(other, _ewise_add_expr_types):
290
+ raise TypeError("XXX")
283
291
  return _ewise_infix_expr(other, self, method="ewise_mult", within="__rand__")
284
292
 
285
293
  def __matmul__(self, other):
@@ -375,8 +375,7 @@ def lookup_dtype(key, value=None):
375
375
 
376
376
 
377
377
  def unify(type1, type2, *, is_left_scalar=False, is_right_scalar=False):
378
- """
379
- Returns a type that can hold both type1 and type2.
378
+ """Returns a type that can hold both type1 and type2.
380
379
 
381
380
  For example:
382
381
  unify(INT32, INT64) -> INT64
@@ -147,13 +147,13 @@ class IndexerResolver:
147
147
  return self.indices[0]._py_index()
148
148
 
149
149
  def parse_indices(self, indices, shape):
150
- """
151
- Returns
150
+ """Returns
152
151
  -------
153
152
  [(rows, rowsize), (cols, colsize)] for Matrix
154
153
  [(idx, idx_size)] for Vector
155
154
 
156
155
  Within each tuple, if the index is of type int, the size will be None
156
+
157
157
  """
158
158
  if len(shape) == 1:
159
159
  if type(indices) is tuple:
@@ -312,8 +312,8 @@ class AmbiguousAssignOrExtract:
312
312
  Updater(self.parent, opts=opts)._setitem(self.resolved_indexes, expr, is_submask=False)
313
313
 
314
314
  def new(self, dtype=None, *, mask=None, input_mask=None, name=None, **opts):
315
- """
316
- Force extraction of the indexes into a new object
315
+ """Force extraction of the indexes into a new object.
316
+
317
317
  dtype and mask are the only controllable parameters.
318
318
  """
319
319
  if input_mask is not None:
@@ -1,8 +1,9 @@
1
1
  from .. import backend, binary
2
2
  from ..dtypes import BOOL
3
+ from ..exceptions import DimensionMismatch
3
4
  from ..monoid import land, lor
4
5
  from ..semiring import any_pair
5
- from . import automethods, utils
6
+ from . import automethods, recorder, utils
6
7
  from .base import _expect_op, _expect_type
7
8
  from .expr import InfixExprBase
8
9
  from .mask import Mask
@@ -125,6 +126,19 @@ class ScalarEwiseAddExpr(ScalarInfixExpr):
125
126
 
126
127
  _to_expr = _ewise_add_to_expr
127
128
 
129
+ # Allow e.g. `plus(x | y | z)`
130
+ __or__ = Scalar.__or__
131
+ __ror__ = Scalar.__ror__
132
+ _ewise_add = Scalar._ewise_add
133
+ _ewise_union = Scalar._ewise_union
134
+
135
+ # Don't allow e.g. `plus(x | y & z)`
136
+ def __and__(self, other):
137
+ raise TypeError("XXX")
138
+
139
+ def __rand__(self, other):
140
+ raise TypeError("XXX")
141
+
128
142
 
129
143
  class ScalarEwiseMultExpr(ScalarInfixExpr):
130
144
  __slots__ = ()
@@ -134,6 +148,18 @@ class ScalarEwiseMultExpr(ScalarInfixExpr):
134
148
 
135
149
  _to_expr = _ewise_mult_to_expr
136
150
 
151
+ # Allow e.g. `plus(x & y & z)`
152
+ __and__ = Scalar.__and__
153
+ __rand__ = Scalar.__rand__
154
+ _ewise_mult = Scalar._ewise_mult
155
+
156
+ # Don't allow e.g. `plus(x | y & z)`
157
+ def __or__(self, other):
158
+ raise TypeError("XXX")
159
+
160
+ def __ror__(self, other):
161
+ raise TypeError("XXX")
162
+
137
163
 
138
164
  class ScalarMatMulExpr(ScalarInfixExpr):
139
165
  __slots__ = ()
@@ -210,7 +236,6 @@ class VectorInfixExpr(InfixExprBase):
210
236
  to_coo = wrapdoc(Vector.to_coo)(property(automethods.to_coo))
211
237
  to_dense = wrapdoc(Vector.to_dense)(property(automethods.to_dense))
212
238
  to_dict = wrapdoc(Vector.to_dict)(property(automethods.to_dict))
213
- to_values = wrapdoc(Vector.to_values)(property(automethods.to_values))
214
239
  vxm = wrapdoc(Vector.vxm)(property(automethods.vxm))
215
240
  wait = wrapdoc(Vector.wait)(property(automethods.wait))
216
241
  # These raise exceptions
@@ -238,6 +263,15 @@ class VectorEwiseAddExpr(VectorInfixExpr):
238
263
 
239
264
  _to_expr = _ewise_add_to_expr
240
265
 
266
+ # Allow e.g. `plus(x | y | z)`
267
+ __or__ = Vector.__or__
268
+ __ror__ = Vector.__ror__
269
+ _ewise_add = Vector._ewise_add
270
+ _ewise_union = Vector._ewise_union
271
+ # Don't allow e.g. `plus(x | y & z)`
272
+ __and__ = ScalarEwiseAddExpr.__and__ # raises
273
+ __rand__ = ScalarEwiseAddExpr.__rand__ # raises
274
+
241
275
 
242
276
  class VectorEwiseMultExpr(VectorInfixExpr):
243
277
  __slots__ = ()
@@ -247,6 +281,14 @@ class VectorEwiseMultExpr(VectorInfixExpr):
247
281
 
248
282
  _to_expr = _ewise_mult_to_expr
249
283
 
284
+ # Allow e.g. `plus(x & y & z)`
285
+ __and__ = Vector.__and__
286
+ __rand__ = Vector.__rand__
287
+ _ewise_mult = Vector._ewise_mult
288
+ # Don't allow e.g. `plus(x | y & z)`
289
+ __or__ = ScalarEwiseMultExpr.__or__ # raises
290
+ __ror__ = ScalarEwiseMultExpr.__ror__ # raises
291
+
250
292
 
251
293
  class VectorMatMulExpr(VectorInfixExpr):
252
294
  __slots__ = "method_name"
@@ -258,6 +300,11 @@ class VectorMatMulExpr(VectorInfixExpr):
258
300
  self.method_name = method_name
259
301
  self._size = size
260
302
 
303
+ __matmul__ = Vector.__matmul__
304
+ __rmatmul__ = Vector.__rmatmul__
305
+ _inner = Vector._inner
306
+ _vxm = Vector._vxm
307
+
261
308
 
262
309
  utils._output_types[VectorEwiseAddExpr] = Vector
263
310
  utils._output_types[VectorEwiseMultExpr] = Vector
@@ -348,7 +395,6 @@ class MatrixInfixExpr(InfixExprBase):
348
395
  to_dense = wrapdoc(Matrix.to_dense)(property(automethods.to_dense))
349
396
  to_dicts = wrapdoc(Matrix.to_dicts)(property(automethods.to_dicts))
350
397
  to_edgelist = wrapdoc(Matrix.to_edgelist)(property(automethods.to_edgelist))
351
- to_values = wrapdoc(Matrix.to_values)(property(automethods.to_values))
352
398
  wait = wrapdoc(Matrix.wait)(property(automethods.wait))
353
399
  # These raise exceptions
354
400
  __array__ = Matrix.__array__
@@ -375,6 +421,15 @@ class MatrixEwiseAddExpr(MatrixInfixExpr):
375
421
 
376
422
  _to_expr = _ewise_add_to_expr
377
423
 
424
+ # Allow e.g. `plus(x | y | z)`
425
+ __or__ = Matrix.__or__
426
+ __ror__ = Matrix.__ror__
427
+ _ewise_add = Matrix._ewise_add
428
+ _ewise_union = Matrix._ewise_union
429
+ # Don't allow e.g. `plus(x | y & z)`
430
+ __and__ = VectorEwiseAddExpr.__and__ # raises
431
+ __rand__ = VectorEwiseAddExpr.__rand__ # raises
432
+
378
433
 
379
434
  class MatrixEwiseMultExpr(MatrixInfixExpr):
380
435
  __slots__ = ()
@@ -384,6 +439,14 @@ class MatrixEwiseMultExpr(MatrixInfixExpr):
384
439
 
385
440
  _to_expr = _ewise_mult_to_expr
386
441
 
442
+ # Allow e.g. `plus(x & y & z)`
443
+ __and__ = Matrix.__and__
444
+ __rand__ = Matrix.__rand__
445
+ _ewise_mult = Matrix._ewise_mult
446
+ # Don't allow e.g. `plus(x | y & z)`
447
+ __or__ = VectorEwiseMultExpr.__or__ # raises
448
+ __ror__ = VectorEwiseMultExpr.__ror__ # raises
449
+
387
450
 
388
451
  class MatrixMatMulExpr(MatrixInfixExpr):
389
452
  __slots__ = ()
@@ -396,49 +459,73 @@ class MatrixMatMulExpr(MatrixInfixExpr):
396
459
  self._nrows = nrows
397
460
  self._ncols = ncols
398
461
 
462
+ __matmul__ = Matrix.__matmul__
463
+ __rmatmul__ = Matrix.__rmatmul__
464
+ _mxm = Matrix._mxm
465
+ _mxv = Matrix._mxv
466
+
399
467
 
400
468
  utils._output_types[MatrixEwiseAddExpr] = Matrix
401
469
  utils._output_types[MatrixEwiseMultExpr] = Matrix
402
470
  utils._output_types[MatrixMatMulExpr] = Matrix
403
471
 
404
472
 
473
+ def _dummy(obj, obj_type):
474
+ with recorder.skip_record:
475
+ return output_type(obj)(BOOL, *obj.shape, name="")
476
+
477
+
478
+ def _mismatched(left, right, method, op):
479
+ # Create dummy expression to raise on incompatible dimensions
480
+ getattr(_dummy(left) if isinstance(left, InfixExprBase) else left, method)(
481
+ _dummy(right) if isinstance(right, InfixExprBase) else right, op
482
+ )
483
+ raise DimensionMismatch # pragma: no cover
484
+
485
+
405
486
  def _ewise_infix_expr(left, right, *, method, within):
406
487
  left_type = output_type(left)
407
488
  right_type = output_type(right)
408
489
 
409
490
  types = {Vector, Matrix, TransposedMatrix}
410
491
  if left_type in types and right_type in types:
411
- # Create dummy expression to check compatibility of dimensions, etc.
412
- expr = getattr(left, method)(right, binary.any)
413
- if expr.output_type is Vector:
414
- if method == "ewise_mult":
415
- return VectorEwiseMultExpr(left, right)
416
- return VectorEwiseAddExpr(left, right)
492
+ if left_type is Vector:
493
+ if right_type is Vector:
494
+ if left._size != right._size:
495
+ _mismatched(left, right, method, binary.first)
496
+ if method == "ewise_mult":
497
+ return VectorEwiseMultExpr(left, right)
498
+ return VectorEwiseAddExpr(left, right)
499
+ if left._size != right._nrows:
500
+ _mismatched(left, right, method, binary.first)
501
+ elif right_type is Vector:
502
+ if left._ncols != right._size:
503
+ _mismatched(left, right, method, binary.first)
504
+ elif left.shape != right.shape:
505
+ _mismatched(left, right, method, binary.first)
417
506
  if method == "ewise_mult":
418
507
  return MatrixEwiseMultExpr(left, right)
419
508
  return MatrixEwiseAddExpr(left, right)
509
+
420
510
  if within == "__or__" and isinstance(right, Mask):
421
511
  return right.__ror__(left)
422
512
  if within == "__and__" and isinstance(right, Mask):
423
513
  return right.__rand__(left)
424
514
  if left_type in types:
425
515
  left._expect_type(right, tuple(types), within=within, argname="right")
426
- elif right_type in types:
516
+ if right_type in types:
427
517
  right._expect_type(left, tuple(types), within=within, argname="left")
428
- elif left_type is Scalar:
429
- # Create dummy expression to check compatibility of dimensions, etc.
430
- expr = getattr(left, method)(right, binary.any)
518
+ if left_type is Scalar:
431
519
  if method == "ewise_mult":
432
520
  return ScalarEwiseMultExpr(left, right)
433
521
  return ScalarEwiseAddExpr(left, right)
434
- elif right_type is Scalar:
435
- # Create dummy expression to check compatibility of dimensions, etc.
436
- expr = getattr(right, method)(left, binary.any)
522
+ if right_type is Scalar:
437
523
  if method == "ewise_mult":
438
524
  return ScalarEwiseMultExpr(right, left)
439
525
  return ScalarEwiseAddExpr(right, left)
440
- else: # pragma: no cover (sanity)
441
- raise TypeError(f"Bad types for ewise infix: {type(left).__name__}, {type(right).__name__}")
526
+ raise TypeError( # pragma: no cover (sanity)
527
+ f"Bad types for ewise infix: {type(left).__name__}, {type(right).__name__}"
528
+ )
442
529
 
443
530
 
444
531
  def _matmul_infix_expr(left, right, *, within):
@@ -447,55 +534,55 @@ def _matmul_infix_expr(left, right, *, within):
447
534
 
448
535
  if left_type is Vector:
449
536
  if right_type is Matrix or right_type is TransposedMatrix:
450
- method = "vxm"
451
- elif right_type is Vector:
452
- method = "inner"
453
- else:
454
- right = left._expect_type(
455
- right,
456
- (Matrix, TransposedMatrix),
457
- within=within,
458
- argname="right",
459
- )
460
- elif left_type is Matrix or left_type is TransposedMatrix:
537
+ if left._size != right._nrows:
538
+ _mismatched(left, right, "vxm", any_pair[BOOL])
539
+ return VectorMatMulExpr(left, right, method_name="vxm", size=right._ncols)
461
540
  if right_type is Vector:
462
- method = "mxv"
463
- elif right_type is Matrix or right_type is TransposedMatrix:
464
- method = "mxm"
465
- else:
466
- right = left._expect_type(
467
- right,
468
- (Vector, Matrix, TransposedMatrix),
469
- within=within,
470
- argname="right",
471
- )
472
- elif right_type is Vector:
473
- left = right._expect_type(
541
+ if left._size != right._size:
542
+ _mismatched(left, right, "inner", any_pair[BOOL])
543
+ return ScalarMatMulExpr(left, right)
544
+ left._expect_type(
545
+ right,
546
+ (Matrix, TransposedMatrix, Vector),
547
+ within=within,
548
+ argname="right",
549
+ )
550
+ if left_type is Matrix or left_type is TransposedMatrix:
551
+ if right_type is Vector:
552
+ if left._ncols != right._size:
553
+ _mismatched(left, right, "mxv", any_pair[BOOL])
554
+ return VectorMatMulExpr(left, right, method_name="mxv", size=left._nrows)
555
+ if right_type is Matrix or right_type is TransposedMatrix:
556
+ if left._ncols != right._nrows:
557
+ _mismatched(left, right, "mxm", any_pair[BOOL])
558
+ return MatrixMatMulExpr(left, right, nrows=left._nrows, ncols=right._ncols)
559
+ left._expect_type(
560
+ right,
561
+ (Vector, Matrix, TransposedMatrix),
562
+ within=within,
563
+ argname="right",
564
+ )
565
+ if right_type is Vector:
566
+ right._expect_type(
474
567
  left,
475
568
  (Matrix, TransposedMatrix),
476
569
  within=within,
477
570
  argname="left",
478
571
  )
479
- elif right_type is Matrix or right_type is TransposedMatrix:
480
- left = right._expect_type(
572
+ if right_type is Matrix or right_type is TransposedMatrix:
573
+ right._expect_type(
481
574
  left,
482
575
  (Vector, Matrix, TransposedMatrix),
483
576
  within=within,
484
577
  argname="left",
485
578
  )
486
- else: # pragma: no cover (sanity)
487
- raise TypeError(
488
- f"Bad types for matmul infix: {type(left).__name__}, {type(right).__name__}"
489
- )
579
+ raise TypeError( # pragma: no cover (sanity)
580
+ f"Bad types for matmul infix: {type(left).__name__}, {type(right).__name__}"
581
+ )
490
582
 
491
- # Create dummy expression to check compatibility of dimensions, etc.
492
- expr = getattr(left, method)(right, any_pair[bool])
493
- if expr.output_type is Vector:
494
- return VectorMatMulExpr(left, right, method_name=method, size=expr._size)
495
- if expr.output_type is Matrix:
496
- return MatrixMatMulExpr(left, right, nrows=expr._nrows, ncols=expr._ncols)
497
- return ScalarMatMulExpr(left, right)
498
583
 
584
+ _ewise_add_expr_types = (MatrixEwiseAddExpr, VectorEwiseAddExpr, ScalarEwiseAddExpr)
585
+ _ewise_mult_expr_types = (MatrixEwiseMultExpr, VectorEwiseMultExpr, ScalarEwiseMultExpr)
499
586
 
500
587
  # Import infixmethods, which has side effects
501
588
  from . import infixmethods # noqa: E402, F401 isort:skip