nvmath-python 0.5.0__cp313-cp313-win_amd64.whl

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 (174) hide show
  1. nvmath/__init__.pxd +0 -0
  2. nvmath/__init__.py +37 -0
  3. nvmath/_internal/__init__.py +0 -0
  4. nvmath/_internal/layout.py +58 -0
  5. nvmath/_utils.py +363 -0
  6. nvmath/bindings/__init__.pxd +0 -0
  7. nvmath/bindings/__init__.py +44 -0
  8. nvmath/bindings/_internal/__init__.pxd +0 -0
  9. nvmath/bindings/_internal/__init__.py +0 -0
  10. nvmath/bindings/_internal/cublas.cp313-win_amd64.pyd +0 -0
  11. nvmath/bindings/_internal/cublas.pxd +518 -0
  12. nvmath/bindings/_internal/cublasLt.cp313-win_amd64.pyd +0 -0
  13. nvmath/bindings/_internal/cublasLt.pxd +54 -0
  14. nvmath/bindings/_internal/cudss.cp313-win_amd64.pyd +0 -0
  15. nvmath/bindings/_internal/cudss.pxd +44 -0
  16. nvmath/bindings/_internal/cufft.cp313-win_amd64.pyd +0 -0
  17. nvmath/bindings/_internal/cufft.pxd +69 -0
  18. nvmath/bindings/_internal/cufftMp.pxd +77 -0
  19. nvmath/bindings/_internal/curand.cp313-win_amd64.pyd +0 -0
  20. nvmath/bindings/_internal/curand.pxd +42 -0
  21. nvmath/bindings/_internal/cusolver.cp313-win_amd64.pyd +0 -0
  22. nvmath/bindings/_internal/cusolver.pxd +15 -0
  23. nvmath/bindings/_internal/cusolverDn.cp313-win_amd64.pyd +0 -0
  24. nvmath/bindings/_internal/cusolverDn.pxd +386 -0
  25. nvmath/bindings/_internal/cusparse.cp313-win_amd64.pyd +0 -0
  26. nvmath/bindings/_internal/cusparse.pxd +270 -0
  27. nvmath/bindings/_internal/mathdx.cp313-win_amd64.pyd +0 -0
  28. nvmath/bindings/_internal/mathdx.pxd +79 -0
  29. nvmath/bindings/_internal/nvshmem.pxd +29 -0
  30. nvmath/bindings/_internal/utils.cp313-win_amd64.pyd +0 -0
  31. nvmath/bindings/_internal/utils.pxd +186 -0
  32. nvmath/bindings/cublas.cp313-win_amd64.pyd +0 -0
  33. nvmath/bindings/cublas.pxd +545 -0
  34. nvmath/bindings/cublas.pyi +18 -0
  35. nvmath/bindings/cublasLt.cp313-win_amd64.pyd +0 -0
  36. nvmath/bindings/cublasLt.pxd +99 -0
  37. nvmath/bindings/cudss.cp313-win_amd64.pyd +0 -0
  38. nvmath/bindings/cudss.pxd +83 -0
  39. nvmath/bindings/cudss.pyi +249 -0
  40. nvmath/bindings/cufft.cp313-win_amd64.pyd +0 -0
  41. nvmath/bindings/cufft.pxd +114 -0
  42. nvmath/bindings/cufftMp.pxd +124 -0
  43. nvmath/bindings/curand.cp313-win_amd64.pyd +0 -0
  44. nvmath/bindings/curand.pxd +71 -0
  45. nvmath/bindings/cusolver.cp313-win_amd64.pyd +0 -0
  46. nvmath/bindings/cusolver.pxd +60 -0
  47. nvmath/bindings/cusolverDn.cp313-win_amd64.pyd +0 -0
  48. nvmath/bindings/cusolverDn.pxd +410 -0
  49. nvmath/bindings/cusparse.cp313-win_amd64.pyd +0 -0
  50. nvmath/bindings/cusparse.pxd +329 -0
  51. nvmath/bindings/cycublas.cp313-win_amd64.pyd +0 -0
  52. nvmath/bindings/cycublas.pxd +657 -0
  53. nvmath/bindings/cycublasLt.cp313-win_amd64.pyd +0 -0
  54. nvmath/bindings/cycublasLt.pxd +1010 -0
  55. nvmath/bindings/cycudss.cp313-win_amd64.pyd +0 -0
  56. nvmath/bindings/cycudss.pxd +191 -0
  57. nvmath/bindings/cycufft.cp313-win_amd64.pyd +0 -0
  58. nvmath/bindings/cycufft.pxd +320 -0
  59. nvmath/bindings/cycufftMp.pxd +333 -0
  60. nvmath/bindings/cycurand.cp313-win_amd64.pyd +0 -0
  61. nvmath/bindings/cycurand.pxd +146 -0
  62. nvmath/bindings/cycusolver.cp313-win_amd64.pyd +0 -0
  63. nvmath/bindings/cycusolver.pxd +143 -0
  64. nvmath/bindings/cycusolverDn.cp313-win_amd64.pyd +0 -0
  65. nvmath/bindings/cycusolverDn.pxd +414 -0
  66. nvmath/bindings/cycusparse.cp313-win_amd64.pyd +0 -0
  67. nvmath/bindings/cycusparse.pxd +476 -0
  68. nvmath/bindings/cymathdx.cp313-win_amd64.pyd +0 -0
  69. nvmath/bindings/cymathdx.pxd +363 -0
  70. nvmath/bindings/cynvshmem.pxd +126 -0
  71. nvmath/bindings/mathdx.cp313-win_amd64.pyd +0 -0
  72. nvmath/bindings/mathdx.pxd +131 -0
  73. nvmath/bindings/mathdx.pyi +686 -0
  74. nvmath/bindings/nvpl/__init__.pxd +0 -0
  75. nvmath/bindings/nvpl/__init__.py +11 -0
  76. nvmath/bindings/nvpl/_internal/__init__.pxd +0 -0
  77. nvmath/bindings/nvpl/_internal/__init__.py +0 -0
  78. nvmath/bindings/nvpl/_internal/fft.pxd +36 -0
  79. nvmath/bindings/nvpl/cyfft.pxd +87 -0
  80. nvmath/bindings/nvpl/fft.pxd +100 -0
  81. nvmath/bindings/nvshmem.pxd +54 -0
  82. nvmath/device/__init__.py +23 -0
  83. nvmath/device/_deprecated.py +33 -0
  84. nvmath/device/caching.py +51 -0
  85. nvmath/device/common.py +131 -0
  86. nvmath/device/common_backend.py +125 -0
  87. nvmath/device/common_cuda.py +156 -0
  88. nvmath/device/common_mathdx.py +97 -0
  89. nvmath/device/common_numba.py +159 -0
  90. nvmath/device/common_opaque_tensor.py +128 -0
  91. nvmath/device/cublasdx.py +1085 -0
  92. nvmath/device/cublasdx_backend.py +552 -0
  93. nvmath/device/cublasdx_numba.py +528 -0
  94. nvmath/device/cufftdx.py +551 -0
  95. nvmath/device/cufftdx_backend.py +194 -0
  96. nvmath/device/cufftdx_numba.py +123 -0
  97. nvmath/device/curand_kernel.py +9147 -0
  98. nvmath/device/nvrtc.py +95 -0
  99. nvmath/device/patch.py +35 -0
  100. nvmath/device/random.py +417 -0
  101. nvmath/device/random_helpers.py +23 -0
  102. nvmath/device/random_states.py +189 -0
  103. nvmath/device/types.py +11 -0
  104. nvmath/device/vector_types_numba.py +203 -0
  105. nvmath/distributed/__init__.py +117 -0
  106. nvmath/distributed/_internal/__init__.py +0 -0
  107. nvmath/distributed/_internal/nvshmem.py +243 -0
  108. nvmath/distributed/_internal/tensor_ifc_cupy.py +111 -0
  109. nvmath/distributed/_internal/tensor_ifc_numpy.py +53 -0
  110. nvmath/distributed/_internal/tensor_ifc_torch.py +108 -0
  111. nvmath/distributed/_internal/tensor_wrapper.py +59 -0
  112. nvmath/distributed/_utils.py +152 -0
  113. nvmath/distributed/fft/__init__.py +6 -0
  114. nvmath/distributed/fft/_configuration.py +86 -0
  115. nvmath/distributed/fft/fft.py +1737 -0
  116. nvmath/distributed/reshape/__init__.py +6 -0
  117. nvmath/distributed/reshape/_configuration.py +39 -0
  118. nvmath/distributed/reshape/reshape.py +1249 -0
  119. nvmath/fft/__init__.py +7 -0
  120. nvmath/fft/_configuration.py +208 -0
  121. nvmath/fft/_exec_utils.py +116 -0
  122. nvmath/fft/_helpers.py +260 -0
  123. nvmath/fft/fft.py +2346 -0
  124. nvmath/internal/__init__.py +5 -0
  125. nvmath/internal/enum_utils.py +142 -0
  126. nvmath/internal/formatters.py +87 -0
  127. nvmath/internal/mem_limit.py +51 -0
  128. nvmath/internal/package_ifc.py +119 -0
  129. nvmath/internal/package_ifc_cuda.py +43 -0
  130. nvmath/internal/package_ifc_cupy.py +49 -0
  131. nvmath/internal/package_ifc_torch.py +31 -0
  132. nvmath/internal/package_wrapper.py +14 -0
  133. nvmath/internal/tensor_ifc.py +143 -0
  134. nvmath/internal/tensor_ifc_cupy.py +185 -0
  135. nvmath/internal/tensor_ifc_numpy.py +157 -0
  136. nvmath/internal/tensor_ifc_torch.py +115 -0
  137. nvmath/internal/tensor_wrapper.py +160 -0
  138. nvmath/internal/typemaps.py +154 -0
  139. nvmath/internal/utils.py +634 -0
  140. nvmath/linalg/__init__.py +11 -0
  141. nvmath/linalg/_internal/__init__.py +3 -0
  142. nvmath/linalg/_internal/algo_cap_ifc.py +86 -0
  143. nvmath/linalg/_internal/algo_config_ifc.py +87 -0
  144. nvmath/linalg/_internal/enum_to_tuples.py +64 -0
  145. nvmath/linalg/_internal/epilog_protocol.py +738 -0
  146. nvmath/linalg/_internal/matmul_desc_ifc.py +72 -0
  147. nvmath/linalg/_internal/matmul_pref_ifc.py +65 -0
  148. nvmath/linalg/_internal/matrix_layout_ifc.py +59 -0
  149. nvmath/linalg/_internal/typemaps.py +135 -0
  150. nvmath/linalg/_internal/utils.py +96 -0
  151. nvmath/linalg/advanced/__init__.py +8 -0
  152. nvmath/linalg/advanced/_algorithmmod.py +142 -0
  153. nvmath/linalg/advanced/_configuration.py +320 -0
  154. nvmath/linalg/advanced/helpers/__init__.py +5 -0
  155. nvmath/linalg/advanced/helpers/matmul.py +173 -0
  156. nvmath/linalg/advanced/matmulmod.py +2855 -0
  157. nvmath/memory.py +266 -0
  158. nvmath/sparse/__init__.py +18 -0
  159. nvmath/sparse/_internal/__init__.py +21 -0
  160. nvmath/sparse/_internal/common_utils.py +81 -0
  161. nvmath/sparse/_internal/cudss_config_ifc.py +584 -0
  162. nvmath/sparse/_internal/cudss_data_ifc.py +291 -0
  163. nvmath/sparse/_internal/cudss_utils.py +398 -0
  164. nvmath/sparse/_internal/sparse_csr_ifc.py +154 -0
  165. nvmath/sparse/_internal/sparse_format_helpers.py +88 -0
  166. nvmath/sparse/_internal/sparse_tensor_ifc.py +80 -0
  167. nvmath/sparse/advanced/__init__.py +7 -0
  168. nvmath/sparse/advanced/_configuration.py +150 -0
  169. nvmath/sparse/advanced/direct_solver.py +1705 -0
  170. nvmath_python-0.5.0.dist-info/METADATA +122 -0
  171. nvmath_python-0.5.0.dist-info/RECORD +174 -0
  172. nvmath_python-0.5.0.dist-info/WHEEL +5 -0
  173. nvmath_python-0.5.0.dist-info/licenses/LICENSE +177 -0
  174. nvmath_python-0.5.0.dist-info/top_level.txt +1 -0
nvmath/memory.py ADDED
@@ -0,0 +1,266 @@
1
+ # Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ """Interface for pluggable memory handlers."""
6
+
7
+ __all__ = ["BaseCUDAMemoryManager", "MemoryPointer"]
8
+
9
+ from abc import abstractmethod
10
+ from collections.abc import Callable
11
+ from typing import Protocol, runtime_checkable
12
+ import logging
13
+ import weakref
14
+
15
+ import cuda.core.experimental as ccx
16
+
17
+ from nvmath.internal import utils
18
+ from nvmath.internal.package_ifc_cuda import CUDAPackage
19
+
20
+
21
+ class MemoryPointer:
22
+ """
23
+ An RAII class for a device memory buffer.
24
+
25
+ Args:
26
+ device_ptr: The address of the device memory buffer.
27
+ size: The size of the memory buffer in bytes.
28
+ finalizer: A nullary callable that will be called when the buffer is to be freed.
29
+
30
+ .. seealso:: :class:`numba.cuda.MemoryPointer`
31
+ """
32
+
33
+ def __init__(self, device_ptr: int, size: int, finalizer: None | Callable[[], None]):
34
+ self.device_ptr = device_ptr
35
+ self.size = size
36
+ self._finalizer: weakref.finalize | None
37
+ if finalizer is not None:
38
+ self._finalizer = weakref.finalize(self, finalizer)
39
+ else:
40
+ self._finalizer = None
41
+
42
+ def free(self):
43
+ """
44
+ "Frees" the memory buffer by calling the finalizer.
45
+ """
46
+ if self._finalizer is None:
47
+ return
48
+
49
+ if not self._finalizer.alive:
50
+ raise RuntimeError("The buffer has already been freed.")
51
+ self._finalizer()
52
+
53
+
54
+ @runtime_checkable
55
+ class BaseCUDAMemoryManager(Protocol):
56
+ """
57
+ Protocol for memory manager plugins.
58
+
59
+ .. seealso:: :class:`numba.cuda.BaseCUDAMemoryManager`
60
+ """
61
+
62
+ @abstractmethod
63
+ def __init__(self, device_id: int, logger: logging.Logger):
64
+ raise NotImplementedError
65
+
66
+ @abstractmethod
67
+ def memalloc(self, size: int) -> MemoryPointer:
68
+ """
69
+ Allocate device memory synchronously or on the current stream.
70
+
71
+ Args:
72
+ size: The size of the memory buffer in bytes.
73
+
74
+ Returns:
75
+ An object that owns the allocated memory and is responsible for releasing it (to
76
+ the OS or a pool). The object must have an attribute named ``device_ptr``,
77
+ ``device_pointer``, or ``ptr`` specifying the pointer to the allocated memory
78
+ buffer. See :class:`MemoryPointer` for an example interface.
79
+
80
+ Note:
81
+ Objects of type :class:`numba.cuda.MemoryPointer` as well as
82
+ :class:`cupy.cuda.MemoryPointer` meet the requirements listed above for the
83
+ device memory pointer object.
84
+ """
85
+ raise NotImplementedError
86
+
87
+
88
+ @runtime_checkable
89
+ class BaseCUDAMemoryManagerAsync(Protocol):
90
+ """
91
+ Protocol for async memory manager plugins.
92
+
93
+ .. seealso:: :class:`BaseCUDAMemoryManager`
94
+ """
95
+
96
+ @abstractmethod
97
+ def __init__(self, device_id: int, logger: logging.Logger):
98
+ raise NotImplementedError
99
+
100
+ @abstractmethod
101
+ def memalloc_async(self, size: int, stream: ccx.Stream) -> MemoryPointer:
102
+ """
103
+ Allocate device memory asynchronously on the provided stream.
104
+
105
+ Args:
106
+ size: The size of the memory buffer in bytes.
107
+ stream: A cuda.core.Stream object on which the allocation will be performed.
108
+
109
+ Returns:
110
+ An object that owns the allocated memory and is responsible for releasing it (to
111
+ the OS or a pool). The object must have an attribute named ``device_ptr``,
112
+ ``device_pointer``, or ``ptr`` specifying the pointer to the allocated memory
113
+ buffer. See :class:`MemoryPointer` for an example interface.
114
+
115
+ Note:
116
+ Objects of type :class:`numba.cuda.MemoryPointer` as well as
117
+ :class:`cupy.cuda.MemoryPointer` meet the requirements listed above for the
118
+ device memory pointer object.
119
+ """
120
+ raise NotImplementedError
121
+
122
+
123
+ class _RawCUDAMemoryManager(BaseCUDAMemoryManagerAsync):
124
+ """
125
+ Raw device memory allocator.
126
+
127
+ Args:
128
+ device_id: The ID (int) of the device on which memory is to be allocated.
129
+ logger (logging.Logger): Python Logger object.
130
+ """
131
+
132
+ def __init__(self, device_id: int, logger: logging.Logger):
133
+ """
134
+ __init__(device_id)
135
+ """
136
+ self.device_id = device_id
137
+ self.logger = logger
138
+
139
+ def memalloc_async(self, size: int, stream: ccx.Stream) -> MemoryPointer:
140
+ with utils.device_ctx(self.device_id) as device:
141
+ buffer = device.allocate(size=size, stream=stream)
142
+ device_ptr = int(buffer.handle)
143
+
144
+ self.logger.debug(
145
+ "_RawCUDAMemoryManager (allocate memory): size = %d, ptr = %d, device_id = %d, stream = %s",
146
+ size,
147
+ device_ptr,
148
+ self.device_id,
149
+ stream,
150
+ )
151
+
152
+ def finalizer():
153
+ nonlocal buffer, stream, device_ptr
154
+ self.logger.debug(
155
+ "_RawCUDAMemoryManager (release memory): ptr = %d, device_id = %d, stream = %s",
156
+ device_ptr,
157
+ self.device_id,
158
+ stream,
159
+ )
160
+ with utils.device_ctx(self.device_id):
161
+ buffer.close(stream=stream)
162
+
163
+ return MemoryPointer(device_ptr, size, finalizer=finalizer)
164
+
165
+
166
+ _MEMORY_MANAGER: dict[str, type[BaseCUDAMemoryManager] | type[BaseCUDAMemoryManagerAsync]] = {
167
+ "_raw": _RawCUDAMemoryManager,
168
+ }
169
+
170
+
171
+ def lazy_load_cupy():
172
+ global _MEMORY_MANAGER
173
+ import cupy as cp
174
+ from nvmath.internal.package_ifc_cupy import CupyPackage
175
+
176
+ class _CupyCUDAMemoryManager(BaseCUDAMemoryManagerAsync):
177
+ """
178
+ CuPy device memory allocator.
179
+
180
+ Args:
181
+ device_id: The ID (int) of the device on which memory is to be allocated.
182
+ logger (logging.Logger): Python Logger object.
183
+ """
184
+
185
+ def __init__(self, device_id: int, logger: logging.Logger):
186
+ """
187
+ __init__(device_id)
188
+ """
189
+ self.device_id = device_id
190
+ self.logger = logger
191
+
192
+ def memalloc_async(self, size: int, stream) -> MemoryPointer:
193
+ stream_ctx = CupyPackage.to_stream_context(
194
+ CupyPackage.create_external_stream(self.device_id, CUDAPackage.to_stream_pointer(stream))
195
+ )
196
+ with utils.device_ctx(self.device_id), stream_ctx:
197
+ cp_mem_ptr = cp.cuda.alloc(size)
198
+ device_ptr = cp_mem_ptr.ptr
199
+
200
+ self.logger.debug(
201
+ "_CupyCUDAMemoryManager (allocate memory): size = %d, ptr = %d, device_id = %d, stream = %s",
202
+ size,
203
+ device_ptr,
204
+ self.device_id,
205
+ stream,
206
+ )
207
+
208
+ def finalizer():
209
+ # The cupy MemoryPointer object is RAII, so we keep a reference to it
210
+ # until we don't need it anymore.
211
+ nonlocal cp_mem_ptr, device_ptr
212
+ self.logger.debug("_CupyCUDAMemoryManager (release memory): ptr = %d", device_ptr)
213
+ del cp_mem_ptr
214
+
215
+ return MemoryPointer(device_ptr, size, finalizer=finalizer)
216
+
217
+ _MEMORY_MANAGER["cupy"] = _CupyCUDAMemoryManager
218
+
219
+
220
+ def lazy_load_torch():
221
+ global _MEMORY_MANAGER
222
+
223
+ from torch.cuda import caching_allocator_alloc, caching_allocator_delete
224
+ from nvmath.internal.package_ifc_torch import TorchPackage
225
+
226
+ class _TorchCUDAMemoryManager(BaseCUDAMemoryManagerAsync):
227
+ """
228
+ Torch caching memory allocator.
229
+
230
+ Args:
231
+ device_id: The ID (int) of the device on which memory is to be allocated.
232
+ logger (logging.Logger): Python Logger object.
233
+ """
234
+
235
+ def __init__(self, device_id: int, logger: logging.Logger):
236
+ """
237
+ __init__(device_id)
238
+ """
239
+ self.device_id = device_id
240
+ self.logger = logger
241
+
242
+ def memalloc_async(self, size: int, stream: ccx.Stream) -> MemoryPointer:
243
+ torch_stream = TorchPackage.create_external_stream(self.device_id, CUDAPackage.to_stream_pointer(stream))
244
+ device_ptr = caching_allocator_alloc(size, device=self.device_id, stream=torch_stream)
245
+
246
+ self.logger.debug(
247
+ "_TorchCUDAMemoryManager (allocate memory): size = %d, ptr = %d, device_id = %d, stream = %s",
248
+ size,
249
+ device_ptr,
250
+ self.device_id,
251
+ stream,
252
+ )
253
+
254
+ def finalizer():
255
+ nonlocal device_ptr, stream
256
+ self.logger.debug(
257
+ "_TorchCUDAMemoryManager (release memory): ptr = %d, device_id = %d, stream = %s",
258
+ device_ptr,
259
+ self.device_id,
260
+ stream,
261
+ )
262
+ caching_allocator_delete(device_ptr)
263
+
264
+ return MemoryPointer(device_ptr, size, finalizer=finalizer)
265
+
266
+ _MEMORY_MANAGER["torch"] = _TorchCUDAMemoryManager
@@ -0,0 +1,18 @@
1
+ # Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from nvmath._utils import force_loading_cudss
6
+
7
+ try:
8
+ force_loading_cudss("12")
9
+ except RuntimeError:
10
+ pass
11
+
12
+ del force_loading_cudss
13
+
14
+ from . import advanced # noqa: E402
15
+
16
+ __all__ = [
17
+ "advanced",
18
+ ]
@@ -0,0 +1,21 @@
1
+ # Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from . import common_utils as common_utils
6
+ from . import cudss_config_ifc as cudss_config_ifc
7
+ from . import cudss_data_ifc as cudss_data_ifc
8
+ from . import cudss_utils as cudss_utils
9
+ from . import sparse_csr_ifc as sparse_csr_ifc
10
+ from . import sparse_format_helpers as sparse_format_helpers
11
+ from . import sparse_tensor_ifc as sparse_tensor_ifc
12
+
13
+ __all__ = [
14
+ "common_utils",
15
+ "cudss_config_ifc",
16
+ "cudss_data_ifc",
17
+ "cudss_utils",
18
+ "sparse_csr_ifc",
19
+ "sparse_format_helpers",
20
+ "sparse_tensor_ifc",
21
+ ]
@@ -0,0 +1,81 @@
1
+ # Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ """
6
+ A collection of sparse utilities.
7
+ """
8
+
9
+ import importlib
10
+ from collections.abc import Sequence
11
+
12
+ from nvmath.internal.utils import infer_object_package
13
+ from nvmath.sparse._internal.sparse_format_helpers import PACKAGE_HELPER_MAP
14
+
15
+
16
+ def check_supported_package(native_operands):
17
+ """
18
+ Check if the operands belong to one of the supported packages.
19
+ """
20
+ package = {infer_object_package(o) for o in native_operands}
21
+ if len(package) != 1:
22
+ raise ValueError(f"The sparse operands do not belong to the same package: {package}.")
23
+
24
+ package = package.pop()
25
+ if package not in PACKAGE_HELPER_MAP:
26
+ raise TypeError(f"The sparse operand package {package} is not supported.")
27
+
28
+ return package
29
+
30
+
31
+ def wrap_sparse_operand(native_operand):
32
+ """
33
+ Wrap one "native" sparse operand so that package-agnostic API can be used.
34
+ """
35
+
36
+ helper = PACKAGE_HELPER_MAP[infer_object_package(native_operand)]
37
+ sparse_format = helper.sparse_format_name(native_operand)
38
+ attr_name_map = getattr(helper, f"{sparse_format.lower()}_attribute_names")()
39
+
40
+ module_name = f"nvmath.sparse._internal.sparse_{sparse_format.lower()}_ifc"
41
+ module = importlib.import_module(module_name)
42
+ SparseHolder = getattr(module, f"{sparse_format}TensorHolder")
43
+
44
+ return SparseHolder.create_from_tensor(native_operand, attr_name_map=attr_name_map)
45
+
46
+
47
+ def wrap_sparse_operands(native_operands):
48
+ """
49
+ Wrap each "native" sparse operand so that package-agnostic API can be used.
50
+ """
51
+
52
+ if not isinstance(native_operands, Sequence):
53
+ return wrap_sparse_operand(native_operands)
54
+
55
+ package = check_supported_package(native_operands)
56
+ helper = PACKAGE_HELPER_MAP[package]
57
+
58
+ sparse_format = {helper.sparse_format_name(o) for o in native_operands}
59
+ if len(sparse_format) != 1:
60
+ raise ValueError(f"The sparse operands do not have the same sparse format: {sparse_format}")
61
+ sparse_format = sparse_format.pop()
62
+ attr_name_map = getattr(helper, f"{sparse_format.lower()}_attribute_names")()
63
+
64
+ module_name = f"nvmath.sparse._internal.sparse_{sparse_format.lower()}_ifc"
65
+ module = importlib.import_module(module_name)
66
+ SparseHolder = getattr(module, f"{sparse_format}TensorHolder")
67
+
68
+ return [SparseHolder.create_from_tensor(o, attr_name_map=attr_name_map) for o in native_operands]
69
+
70
+
71
+ # TODO: Unify all the get_attribute functions in internal.utils
72
+ # as get(operands, attribute, attribute_desc).
73
+ def get_operands_index_type(operands):
74
+ """
75
+ Return the index type name of the tensors.
76
+ """
77
+ index_type = operands[0].index_type
78
+ if not all(operand.index_type == index_type for operand in operands):
79
+ index_types = {operand.index_type for operand in operands}
80
+ raise ValueError(f"All operands must have the same index type. The index types found = {index_types}.")
81
+ return index_type