nvmath-python 1.0.0__cp314-cp314t-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 (332) hide show
  1. nvmath/__init__.pxd +0 -0
  2. nvmath/__init__.py +45 -0
  3. nvmath/_internal/__init__.py +0 -0
  4. nvmath/_internal/attribute_ifc_factory.py +330 -0
  5. nvmath/_internal/layout.py +70 -0
  6. nvmath/_internal/templates.py +130 -0
  7. nvmath/_internal/threadsafe.py +106 -0
  8. nvmath/_internal/utils.py +43 -0
  9. nvmath/_internal/workspace.py +490 -0
  10. nvmath/_utils.py +147 -0
  11. nvmath/bindings/__init__.py +60 -0
  12. nvmath/bindings/_internal/__init__.pxd +0 -0
  13. nvmath/bindings/_internal/__init__.py +0 -0
  14. nvmath/bindings/_internal/common_types.pxd +31 -0
  15. nvmath/bindings/_internal/cublas.cp314t-win_amd64.pyd +0 -0
  16. nvmath/bindings/_internal/cublas.pxd +530 -0
  17. nvmath/bindings/_internal/cublasLt.cp314t-win_amd64.pyd +0 -0
  18. nvmath/bindings/_internal/cublasLt.pxd +59 -0
  19. nvmath/bindings/_internal/cublasMp.pxd +52 -0
  20. nvmath/bindings/_internal/cudss.cp314t-win_amd64.pyd +0 -0
  21. nvmath/bindings/_internal/cudss.pxd +54 -0
  22. nvmath/bindings/_internal/cufft.cp314t-win_amd64.pyd +0 -0
  23. nvmath/bindings/_internal/cufft.pxd +70 -0
  24. nvmath/bindings/_internal/cufftMp.pxd +77 -0
  25. nvmath/bindings/_internal/curand.cp314t-win_amd64.pyd +0 -0
  26. nvmath/bindings/_internal/curand.pxd +42 -0
  27. nvmath/bindings/_internal/cusolver.cp314t-win_amd64.pyd +0 -0
  28. nvmath/bindings/_internal/cusolver.pxd +15 -0
  29. nvmath/bindings/_internal/cusolverDn.cp314t-win_amd64.pyd +0 -0
  30. nvmath/bindings/_internal/cusolverDn.pxd +406 -0
  31. nvmath/bindings/_internal/cusolverMp.pxd +71 -0
  32. nvmath/bindings/_internal/cusolverSp.cp314t-win_amd64.pyd +0 -0
  33. nvmath/bindings/_internal/cusolverSp.pxd +75 -0
  34. nvmath/bindings/_internal/cusparse.cp314t-win_amd64.pyd +0 -0
  35. nvmath/bindings/_internal/cusparse.pxd +471 -0
  36. nvmath/bindings/_internal/cusparseLt.cp314t-win_amd64.pyd +0 -0
  37. nvmath/bindings/_internal/cusparseLt.pxd +48 -0
  38. nvmath/bindings/_internal/cutensor.cp314t-win_amd64.pyd +0 -0
  39. nvmath/bindings/_internal/cutensor.pxd +58 -0
  40. nvmath/bindings/_internal/mathdx.cp314t-win_amd64.pyd +0 -0
  41. nvmath/bindings/_internal/mathdx.pxd +116 -0
  42. nvmath/bindings/_internal/nvshmem.pxd +29 -0
  43. nvmath/bindings/_internal/utils.cp314t-win_amd64.pyd +0 -0
  44. nvmath/bindings/_internal/utils.pxd +174 -0
  45. nvmath/bindings/_internal/utils.pyi +10 -0
  46. nvmath/bindings/cublas.cp314t-win_amd64.pyd +0 -0
  47. nvmath/bindings/cublas.pxd +558 -0
  48. nvmath/bindings/cublas.pyi +812 -0
  49. nvmath/bindings/cublasLt.cp314t-win_amd64.pyd +0 -0
  50. nvmath/bindings/cublasLt.pxd +109 -0
  51. nvmath/bindings/cublasLt.pyi +1461 -0
  52. nvmath/bindings/cublasMp.pxd +85 -0
  53. nvmath/bindings/cublasMp.pyi +267 -0
  54. nvmath/bindings/cudss.cp314t-win_amd64.pyd +0 -0
  55. nvmath/bindings/cudss.pxd +98 -0
  56. nvmath/bindings/cudss.pyi +443 -0
  57. nvmath/bindings/cufft.cp314t-win_amd64.pyd +0 -0
  58. nvmath/bindings/cufft.pxd +118 -0
  59. nvmath/bindings/cufft.pyi +301 -0
  60. nvmath/bindings/cufftMp.pxd +124 -0
  61. nvmath/bindings/cufftMp.pyi +326 -0
  62. nvmath/bindings/curand.cp314t-win_amd64.pyd +0 -0
  63. nvmath/bindings/curand.pxd +71 -0
  64. nvmath/bindings/curand.pyi +189 -0
  65. nvmath/bindings/cusolver.cp314t-win_amd64.pyd +0 -0
  66. nvmath/bindings/cusolver.pxd +62 -0
  67. nvmath/bindings/cusolver.pyi +320 -0
  68. nvmath/bindings/cusolverDn.cp314t-win_amd64.pyd +0 -0
  69. nvmath/bindings/cusolverDn.pxd +430 -0
  70. nvmath/bindings/cusolverDn.pyi +422 -0
  71. nvmath/bindings/cusolverMp.pxd +98 -0
  72. nvmath/bindings/cusolverMp.pyi +114 -0
  73. nvmath/bindings/cusolverSp.cp314t-win_amd64.pyd +0 -0
  74. nvmath/bindings/cusolverSp.pxd +95 -0
  75. nvmath/bindings/cusolverSp.pyi +70 -0
  76. nvmath/bindings/cusparse.cp314t-win_amd64.pyd +0 -0
  77. nvmath/bindings/cusparse.pxd +546 -0
  78. nvmath/bindings/cusparse.pyi +1017 -0
  79. nvmath/bindings/cusparseLt.cp314t-win_amd64.pyd +0 -0
  80. nvmath/bindings/cusparseLt.pxd +99 -0
  81. nvmath/bindings/cusparseLt.pyi +252 -0
  82. nvmath/bindings/cutensor.cp314t-win_amd64.pyd +0 -0
  83. nvmath/bindings/cutensor.pxd +98 -0
  84. nvmath/bindings/cutensor.pyi +324 -0
  85. nvmath/bindings/cycublas.cp314t-win_amd64.pyd +0 -0
  86. nvmath/bindings/cycublas.pxd +664 -0
  87. nvmath/bindings/cycublasLt.cp314t-win_amd64.pyd +0 -0
  88. nvmath/bindings/cycublasLt.pxd +1045 -0
  89. nvmath/bindings/cycublasMp.pxd +171 -0
  90. nvmath/bindings/cycudss.cp314t-win_amd64.pyd +0 -0
  91. nvmath/bindings/cycudss.pxd +277 -0
  92. nvmath/bindings/cycufft.cp314t-win_amd64.pyd +0 -0
  93. nvmath/bindings/cycufft.pxd +333 -0
  94. nvmath/bindings/cycufftMp.pxd +342 -0
  95. nvmath/bindings/cycurand.cp314t-win_amd64.pyd +0 -0
  96. nvmath/bindings/cycurand.pxd +141 -0
  97. nvmath/bindings/cycusolver.cp314t-win_amd64.pyd +0 -0
  98. nvmath/bindings/cycusolver.pxd +137 -0
  99. nvmath/bindings/cycusolverDn.cp314t-win_amd64.pyd +0 -0
  100. nvmath/bindings/cycusolverDn.pxd +443 -0
  101. nvmath/bindings/cycusolverMp.pxd +107 -0
  102. nvmath/bindings/cycusolverSp.cp314t-win_amd64.pyd +0 -0
  103. nvmath/bindings/cycusolverSp.pxd +93 -0
  104. nvmath/bindings/cycusparse.cp314t-win_amd64.pyd +0 -0
  105. nvmath/bindings/cycusparse.pxd +679 -0
  106. nvmath/bindings/cycusparseLt.cp314t-win_amd64.pyd +0 -0
  107. nvmath/bindings/cycusparseLt.pxd +135 -0
  108. nvmath/bindings/cycutensor.cp314t-win_amd64.pyd +0 -0
  109. nvmath/bindings/cycutensor.pxd +189 -0
  110. nvmath/bindings/cymathdx.cp314t-win_amd64.pyd +0 -0
  111. nvmath/bindings/cymathdx.pxd +552 -0
  112. nvmath/bindings/cynvshmem.pxd +118 -0
  113. nvmath/bindings/mathdx.cp314t-win_amd64.pyd +0 -0
  114. nvmath/bindings/mathdx.pxd +182 -0
  115. nvmath/bindings/mathdx.pyi +1562 -0
  116. nvmath/bindings/nvpl/__init__.pxd +0 -0
  117. nvmath/bindings/nvpl/__init__.py +13 -0
  118. nvmath/bindings/nvpl/_internal/__init__.pxd +0 -0
  119. nvmath/bindings/nvpl/_internal/__init__.py +0 -0
  120. nvmath/bindings/nvpl/_internal/blas.cp314t-win_amd64.pyd +0 -0
  121. nvmath/bindings/nvpl/_internal/blas.pxd +237 -0
  122. nvmath/bindings/nvpl/_internal/fft.cp314t-win_amd64.pyd +0 -0
  123. nvmath/bindings/nvpl/_internal/fft.pxd +36 -0
  124. nvmath/bindings/nvpl/blas.cp314t-win_amd64.pyd +0 -0
  125. nvmath/bindings/nvpl/blas.pxd +131 -0
  126. nvmath/bindings/nvpl/blas.pyi +168 -0
  127. nvmath/bindings/nvpl/cyblas.cp314t-win_amd64.pyd +0 -0
  128. nvmath/bindings/nvpl/cyblas.pxd +280 -0
  129. nvmath/bindings/nvpl/cyfft.cp314t-win_amd64.pyd +0 -0
  130. nvmath/bindings/nvpl/cyfft.pxd +93 -0
  131. nvmath/bindings/nvpl/fft.cp314t-win_amd64.pyd +0 -0
  132. nvmath/bindings/nvpl/fft.pxd +100 -0
  133. nvmath/bindings/nvpl/fft.pyi +168 -0
  134. nvmath/bindings/nvshmem.pxd +54 -0
  135. nvmath/bindings/nvshmem.pyi +191 -0
  136. nvmath/device/__init__.py +38 -0
  137. nvmath/device/_deprecated.py +33 -0
  138. nvmath/device/common.py +315 -0
  139. nvmath/device/common_backend.py +131 -0
  140. nvmath/device/common_cuda.py +201 -0
  141. nvmath/device/common_numba.py +300 -0
  142. nvmath/device/common_numba_cuda_mlir.py +202 -0
  143. nvmath/device/common_opaque_tensor.py +201 -0
  144. nvmath/device/cublasdx.py +1606 -0
  145. nvmath/device/cublasdx_backend.py +860 -0
  146. nvmath/device/cublasdx_numba.py +1534 -0
  147. nvmath/device/cublasdx_numba_cuda_mlir.py +208 -0
  148. nvmath/device/cufftdx.py +373 -0
  149. nvmath/device/cufftdx_backend.py +220 -0
  150. nvmath/device/cufftdx_numba.py +140 -0
  151. nvmath/device/cufftdx_numba_cuda_mlir.py +79 -0
  152. nvmath/device/curand_kernel.py +9147 -0
  153. nvmath/device/cusolverdx.py +2708 -0
  154. nvmath/device/cusolverdx_backend.py +440 -0
  155. nvmath/device/cusolverdx_numba.py +567 -0
  156. nvmath/device/cusolverdx_numba_cuda_mlir.py +604 -0
  157. nvmath/device/cusolverdx_overload_backend.py +1029 -0
  158. nvmath/device/llvm_array.py +29 -0
  159. nvmath/device/random.py +441 -0
  160. nvmath/device/random_helpers.py +23 -0
  161. nvmath/device/random_states.py +187 -0
  162. nvmath/device/types.py +138 -0
  163. nvmath/device/vector_types_numba.py +259 -0
  164. nvmath/distributed/__init__.py +200 -0
  165. nvmath/distributed/_internal/__init__.py +0 -0
  166. nvmath/distributed/_internal/nccl.py +86 -0
  167. nvmath/distributed/_internal/nvshmem.py +307 -0
  168. nvmath/distributed/_internal/symmetric_memory.py +35 -0
  169. nvmath/distributed/_internal/tensor_ifc.py +70 -0
  170. nvmath/distributed/_internal/tensor_ifc_cupy.py +68 -0
  171. nvmath/distributed/_internal/tensor_ifc_host_device.py +172 -0
  172. nvmath/distributed/_internal/tensor_ifc_numpy.py +46 -0
  173. nvmath/distributed/_internal/tensor_ifc_torch.py +162 -0
  174. nvmath/distributed/_internal/tensor_wrapper.py +81 -0
  175. nvmath/distributed/_utils.py +167 -0
  176. nvmath/distributed/distribution/__init__.py +30 -0
  177. nvmath/distributed/distribution/_configuration.py +39 -0
  178. nvmath/distributed/distribution/distributions.py +1024 -0
  179. nvmath/distributed/distribution/redistribute.py +1284 -0
  180. nvmath/distributed/fft/__init__.py +7 -0
  181. nvmath/distributed/fft/_configuration.py +82 -0
  182. nvmath/distributed/fft/fft.py +2742 -0
  183. nvmath/distributed/linalg/__init__.py +22 -0
  184. nvmath/distributed/linalg/_internal/__init__.py +3 -0
  185. nvmath/distributed/linalg/_internal/epilog_protocol.py +586 -0
  186. nvmath/distributed/linalg/_internal/matmul_desc_ifc.py +28 -0
  187. nvmath/distributed/linalg/advanced/__init__.py +8 -0
  188. nvmath/distributed/linalg/advanced/_configuration.py +171 -0
  189. nvmath/distributed/linalg/advanced/matmulmod.py +3573 -0
  190. nvmath/distributed/linalg/generic/__init__.py +8 -0
  191. nvmath/distributed/linalg/generic/_caching.py +66 -0
  192. nvmath/distributed/linalg/generic/_configuration.py +61 -0
  193. nvmath/distributed/linalg/generic/_factorization.py +172 -0
  194. nvmath/distributed/linalg/generic/_initialization.py +966 -0
  195. nvmath/distributed/linalg/generic/_problem_spec.py +511 -0
  196. nvmath/distributed/linalg/generic/solvermod.py +1368 -0
  197. nvmath/distributed/process_group.py +408 -0
  198. nvmath/fft/__init__.py +7 -0
  199. nvmath/fft/_configuration.py +189 -0
  200. nvmath/fft/_exec_utils.py +82 -0
  201. nvmath/fft/_helpers.py +237 -0
  202. nvmath/fft/fft.py +3122 -0
  203. nvmath/internal/__init__.pxd +3 -0
  204. nvmath/internal/__init__.py +10 -0
  205. nvmath/internal/_bindings.cp314t-win_amd64.pyd +0 -0
  206. nvmath/internal/_bindings.pxd +18 -0
  207. nvmath/internal/_device_utils.py +45 -0
  208. nvmath/internal/_layout/__init__.pxd +3 -0
  209. nvmath/internal/_layout/__init__.py +7 -0
  210. nvmath/internal/_layout/_layout.cp314t-win_amd64.pyd +0 -0
  211. nvmath/internal/_layout/_layout.pxd +1303 -0
  212. nvmath/internal/_layout/_layout.pyi +1145 -0
  213. nvmath/internal/enum_utils.py +142 -0
  214. nvmath/internal/formatters.py +87 -0
  215. nvmath/internal/mem_limit.py +51 -0
  216. nvmath/internal/memory.cp314t-win_amd64.pyd +0 -0
  217. nvmath/internal/memory.pxd +13 -0
  218. nvmath/internal/memory.pyi +50 -0
  219. nvmath/internal/ndbuffer/__init__.pxd +3 -0
  220. nvmath/internal/ndbuffer/__init__.py +9 -0
  221. nvmath/internal/ndbuffer/_copy_kernel.cp314t-win_amd64.pyd +0 -0
  222. nvmath/internal/ndbuffer/_copy_kernel.pxd +10 -0
  223. nvmath/internal/ndbuffer/_jit.cp314t-win_amd64.pyd +0 -0
  224. nvmath/internal/ndbuffer/_jit.pxd +7 -0
  225. nvmath/internal/ndbuffer/_ndbuffer.cp314t-win_amd64.pyd +0 -0
  226. nvmath/internal/ndbuffer/_ndbuffer.pxd +40 -0
  227. nvmath/internal/ndbuffer/_ndbuffer.pyi +463 -0
  228. nvmath/internal/ndbuffer/copy_kernel/args.h +34 -0
  229. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/array_view.h +52 -0
  230. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/elementwise.h +68 -0
  231. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/grid_indexer.h +69 -0
  232. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/transposed.h +242 -0
  233. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/type_utils.h +39 -0
  234. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/utils.h +132 -0
  235. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/vec.h +159 -0
  236. nvmath/internal/ndbuffer/copy_kernel/elementwise.h +53 -0
  237. nvmath/internal/ndbuffer/copy_kernel/transposed.h +58 -0
  238. nvmath/internal/package_ifc.py +168 -0
  239. nvmath/internal/package_ifc_cuda.py +57 -0
  240. nvmath/internal/package_ifc_cupy.py +67 -0
  241. nvmath/internal/package_ifc_torch.py +69 -0
  242. nvmath/internal/package_wrapper.py +14 -0
  243. nvmath/internal/tensor_ifc.py +179 -0
  244. nvmath/internal/tensor_ifc_cupy.py +234 -0
  245. nvmath/internal/tensor_ifc_ndbuffer.py +147 -0
  246. nvmath/internal/tensor_ifc_numpy.py +184 -0
  247. nvmath/internal/tensor_ifc_torch.py +178 -0
  248. nvmath/internal/tensor_wrapper.py +160 -0
  249. nvmath/internal/typemaps.py +113 -0
  250. nvmath/internal/utils.py +805 -0
  251. nvmath/linalg/__init__.py +56 -0
  252. nvmath/linalg/_internal/__init__.py +3 -0
  253. nvmath/linalg/_internal/algo_cap_ifc.py +82 -0
  254. nvmath/linalg/_internal/algo_config_ifc.py +43 -0
  255. nvmath/linalg/_internal/batch.py +234 -0
  256. nvmath/linalg/_internal/enum_to_tuples.py +64 -0
  257. nvmath/linalg/_internal/epilog_protocol.py +766 -0
  258. nvmath/linalg/_internal/layout.py +624 -0
  259. nvmath/linalg/_internal/matmul_desc_ifc.py +28 -0
  260. nvmath/linalg/_internal/matmul_pref_ifc.py +27 -0
  261. nvmath/linalg/_internal/matrix_layout_ifc.py +26 -0
  262. nvmath/linalg/_internal/solver_utils.py +432 -0
  263. nvmath/linalg/_internal/typemaps.py +144 -0
  264. nvmath/linalg/_internal/utils.py +157 -0
  265. nvmath/linalg/advanced/__init__.py +8 -0
  266. nvmath/linalg/advanced/_algorithmmod.py +170 -0
  267. nvmath/linalg/advanced/_configuration.py +351 -0
  268. nvmath/linalg/advanced/helpers/__init__.py +5 -0
  269. nvmath/linalg/advanced/helpers/matmul.py +1316 -0
  270. nvmath/linalg/advanced/matmulmod.py +3734 -0
  271. nvmath/linalg/generic/__init__.py +53 -0
  272. nvmath/linalg/generic/_configuration/__init__.py +39 -0
  273. nvmath/linalg/generic/_configuration/layout.py +263 -0
  274. nvmath/linalg/generic/_configuration/match.py +734 -0
  275. nvmath/linalg/generic/_configuration/qualifiers.py +493 -0
  276. nvmath/linalg/generic/_configuration/solver_configuration.py +59 -0
  277. nvmath/linalg/generic/_configuration/wrap.py +217 -0
  278. nvmath/linalg/generic/_dtype.py +15 -0
  279. nvmath/linalg/generic/matmulmod.py +2094 -0
  280. nvmath/linalg/generic/solvermod.py +1301 -0
  281. nvmath/memory.py +279 -0
  282. nvmath/sparse/__init__.py +38 -0
  283. nvmath/sparse/_internal/__init__.py +21 -0
  284. nvmath/sparse/_internal/common_utils.py +147 -0
  285. nvmath/sparse/_internal/cudss_config_ifc.py +702 -0
  286. nvmath/sparse/_internal/cudss_data_ifc.py +399 -0
  287. nvmath/sparse/_internal/cudss_utils.py +506 -0
  288. nvmath/sparse/_internal/cusparse_utils.py +382 -0
  289. nvmath/sparse/_internal/sparse_bsc_ifc.py +303 -0
  290. nvmath/sparse/_internal/sparse_bsr_ifc.py +305 -0
  291. nvmath/sparse/_internal/sparse_coo_ifc.py +256 -0
  292. nvmath/sparse/_internal/sparse_csc_ifc.py +268 -0
  293. nvmath/sparse/_internal/sparse_csr_ifc.py +288 -0
  294. nvmath/sparse/_internal/sparse_dia_ifc.py +242 -0
  295. nvmath/sparse/_internal/sparse_format_helpers.py +601 -0
  296. nvmath/sparse/_internal/sparse_tensor_ifc.py +133 -0
  297. nvmath/sparse/_internal/sparse_ust_ifc.py +141 -0
  298. nvmath/sparse/_internal/utils.py +56 -0
  299. nvmath/sparse/advanced/__init__.py +7 -0
  300. nvmath/sparse/advanced/_configuration.py +227 -0
  301. nvmath/sparse/advanced/direct_solver.py +2069 -0
  302. nvmath/sparse/generic/__init__.py +7 -0
  303. nvmath/sparse/generic/_configuration.py +129 -0
  304. nvmath/sparse/generic/_helpers.py +137 -0
  305. nvmath/sparse/generic/_thunks.py +21 -0
  306. nvmath/sparse/generic/matmulmod.py +2353 -0
  307. nvmath/sparse/ust/__init__.py +7 -0
  308. nvmath/sparse/ust/_converters.py +422 -0
  309. nvmath/sparse/ust/_cpp.py +28 -0
  310. nvmath/sparse/ust/_drawer.py +565 -0
  311. nvmath/sparse/ust/_emitter.py +1033 -0
  312. nvmath/sparse/ust/_jit.py +188 -0
  313. nvmath/sparse/ust/_kernel.py +282 -0
  314. nvmath/sparse/ust/_utils.py +149 -0
  315. nvmath/sparse/ust/interfaces/__init__.py +0 -0
  316. nvmath/sparse/ust/interfaces/torch_interface.py +476 -0
  317. nvmath/sparse/ust/tensor.py +1016 -0
  318. nvmath/sparse/ust/tensor_format.py +957 -0
  319. nvmath/tensor/__init__.py +6 -0
  320. nvmath/tensor/_configuration.py +120 -0
  321. nvmath/tensor/_internal/__init__.py +3 -0
  322. nvmath/tensor/_internal/cutensor_config_ifc.py +279 -0
  323. nvmath/tensor/_internal/cutensor_utils.py +230 -0
  324. nvmath/tensor/_internal/data.py +43 -0
  325. nvmath/tensor/_internal/einsum_parser.py +444 -0
  326. nvmath/tensor/_internal/typemaps.py +96 -0
  327. nvmath/tensor/contract.py +1900 -0
  328. nvmath_python-1.0.0.dist-info/METADATA +134 -0
  329. nvmath_python-1.0.0.dist-info/RECORD +332 -0
  330. nvmath_python-1.0.0.dist-info/WHEEL +5 -0
  331. nvmath_python-1.0.0.dist-info/licenses/LICENSE +177 -0
  332. nvmath_python-1.0.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,305 @@
1
+ # Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ """
6
+ Interface to seamlessly use BSR tensors from different libraries.
7
+ """
8
+
9
+ from __future__ import annotations # allows typehint of class methods to return the self class
10
+
11
+ __all__ = ["BSRTensorHolder"]
12
+
13
+ from typing import Literal, TypeVar
14
+
15
+ from nvmath._internal.layout import check_monotonic_strides, is_contiguous_and_dense
16
+ from nvmath.internal import tensor_wrapper
17
+ from nvmath.internal.package_ifc import StreamHolder
18
+ from nvmath.internal.tensor_ifc import TensorHolder
19
+ from nvmath.internal.utils import infer_object_package
20
+
21
+ from .sparse_tensor_ifc import SparseTensorHolder
22
+
23
+ """
24
+ A generic type for the third-party BSRTensor which a BSRTensorHolder implementation wraps
25
+ around.
26
+ """
27
+ BSRTensor = TypeVar("BSRTensor")
28
+
29
+
30
+ class BSRTensorHolder(SparseTensorHolder):
31
+ """
32
+ A simple wrapper type for BSR sparse tensors to make the API package-agnostic. The
33
+ naming convention is sparse format name with the suffix "TensorHolder", which convention
34
+ is used in the sparse format helper.
35
+
36
+ Since the implementation is in terms of our dense tensor abstraction, package-specific
37
+ implementation is not needed.
38
+ """
39
+
40
+ _format_name: str = "BSR"
41
+
42
+ def __init__(
43
+ self, block_size, block_order, crow_indices, col_indices, values, *, attr_name_map=None, shape=None, tensor=None
44
+ ):
45
+ # tensor is the native tensor.
46
+ self.tensor = tensor
47
+
48
+ # The block size is a sequence of integers.
49
+ self._block_size = block_size
50
+
51
+ # The block order is "left" or "right".
52
+ self._block_order = block_order
53
+
54
+ # attr_name_map is the canonical attribute name to package attribute name map.
55
+ # It is set when constructing from a tensor, otherwise it is None.
56
+ self._attr_name_map = attr_name_map
57
+
58
+ assert (shape is not None) ^ (tensor is not None), "Internal error."
59
+
60
+ if shape is not None:
61
+ self._shape = shape
62
+ else:
63
+ self._shape = tuple(tensor.shape)
64
+
65
+ # Wrap constituent dense tensors, if required.
66
+ if not isinstance(crow_indices, TensorHolder):
67
+ crow_indices = tensor_wrapper.wrap_operand(crow_indices)
68
+
69
+ if not isinstance(col_indices, TensorHolder):
70
+ col_indices = tensor_wrapper.wrap_operand(col_indices)
71
+
72
+ if not isinstance(values, TensorHolder):
73
+ values = tensor_wrapper.wrap_operand(values)
74
+
75
+ # The wrapped constituent dense tensors.
76
+ self._crow_indices = crow_indices
77
+ self._col_indices = col_indices
78
+ self._values = values
79
+
80
+ # Ensure constituent dense tensors are all on the same device.
81
+ device_ids = {d.device_id for d in (self._crow_indices, self._col_indices, self._values)}
82
+ message = f"Internal error: the arrays defining the sparse format aren't on the same device {device_ids}."
83
+ assert len(device_ids) == 1, message
84
+ self._device_id = device_ids.pop()
85
+
86
+ self._device = self._values.device
87
+
88
+ # Capture the native tensor package for use in reset_unchecked().
89
+ self.tensor_package = infer_object_package(self.tensor)
90
+
91
+ # The tensor holder type for the dense constituent tensors (take from values, since
92
+ # all constituent tensors have the same type).
93
+ self._dense_tensorholder_type = values.__class__
94
+
95
+ @classmethod
96
+ def create_from_tensor(cls, tensor, *, attr_name_map=None):
97
+ assert attr_name_map is not None, "Internal error."
98
+
99
+ # tensor is the native tensor.
100
+ # For UST, the buffers will be CuPy ndarrays.
101
+ block_size = attr_name_map["block_size"](tensor)
102
+ block_order = attr_name_map["block_order"](tensor)
103
+ crow_indices = attr_name_map["crow_indices"](tensor)
104
+ col_indices = attr_name_map["col_indices"](tensor)
105
+ values = attr_name_map["values"](tensor)
106
+ return BSRTensorHolder(
107
+ block_size, block_order, crow_indices, col_indices, values, attr_name_map=attr_name_map, tensor=tensor
108
+ )
109
+
110
+ @property
111
+ def attr_name_map(self):
112
+ return self._attr_name_map
113
+
114
+ @property
115
+ def device(self):
116
+ return self._device
117
+
118
+ @property
119
+ def device_id(self):
120
+ return self._device_id
121
+
122
+ @property
123
+ def dtype(self):
124
+ return self._values.dtype
125
+
126
+ @property
127
+ def index_type(self):
128
+ return self._crow_indices.dtype
129
+
130
+ @property
131
+ def format_name(self) -> str:
132
+ return BSRTensorHolder._format_name
133
+
134
+ @property
135
+ def num_dimensions(self):
136
+ return len(self._shape)
137
+
138
+ @property
139
+ def shape(self):
140
+ return self._shape
141
+
142
+ @property
143
+ def block_size(self):
144
+ return self._block_size
145
+
146
+ @property
147
+ def block_order(self):
148
+ return self._block_order
149
+
150
+ @property
151
+ def crow_indices(self) -> TensorHolder:
152
+ """The TensorHolder object wrapping the crow_indices array."""
153
+ return self._crow_indices
154
+
155
+ @property
156
+ def col_indices(self) -> TensorHolder:
157
+ """The TensorHolder object wrapping the col_indices array."""
158
+ return self._col_indices
159
+
160
+ @property
161
+ def values(self) -> TensorHolder:
162
+ """The TensorHolder object wrapping the values array."""
163
+ return self._values
164
+
165
+ def to(self, device_id: int | Literal["cpu"], stream_holder: StreamHolder | None):
166
+ """Copy the BSRTensor representation to a different device.
167
+
168
+ No copy is performed if the BSRTensor is already on the requested device.
169
+ """
170
+ if self.tensor_package == "nvmath":
171
+ return super().to(device_id=device_id, stream_holder=stream_holder)
172
+
173
+ target_crow_indices = self.crow_indices.to(device_id=device_id, stream_holder=stream_holder)
174
+ target_col_indices = self.col_indices.to(device_id=device_id, stream_holder=stream_holder)
175
+ target_values = self.values.to(device_id=device_id, stream_holder=stream_holder)
176
+
177
+ return BSRTensorHolder(
178
+ self.block_size,
179
+ self.block_order,
180
+ target_crow_indices,
181
+ target_col_indices,
182
+ target_values,
183
+ attr_name_map=self.attr_name_map,
184
+ shape=self.shape,
185
+ )
186
+
187
+ def copy_(self, src, stream_holder: StreamHolder | None) -> None:
188
+ """Overwrite self.tensor (in-place) with a copy of src (BSRTensor)."""
189
+
190
+ self._block_size = src.block_size
191
+ self._block_order = src.block_order
192
+ self.crow_indices.copy_(src=src.crow_indices, stream_holder=stream_holder)
193
+ self.col_indices.copy_(src=src.col_indices, stream_holder=stream_holder)
194
+ self.values.copy_(src=src.values, stream_holder=stream_holder)
195
+
196
+ def to_ust(self, *, stream):
197
+ from nvmath.sparse.ust.tensor import Tensor
198
+ from nvmath.sparse.ust.tensor_format import NamedFormats
199
+
200
+ wrapped = self
201
+ tensor = wrapped.tensor
202
+ if not (wrapped.attr_name_map["is_coalesced"](tensor) and wrapped.attr_name_map["has_sorted_indices"](tensor)):
203
+ raise ValueError(
204
+ "The BSR tensor is not coalesced (metadata sorted with duplicates removed). \
205
+ To coalesce, use the operation provided by your sparse tensor library: `coalesce()`, `sum_duplicates()`, ..."
206
+ )
207
+
208
+ if not (
209
+ is_contiguous_and_dense(wrapped.crow_indices.shape, wrapped.crow_indices.strides)
210
+ and is_contiguous_and_dense(wrapped.col_indices.shape, wrapped.col_indices.strides)
211
+ and is_contiguous_and_dense(wrapped.values.shape, wrapped.values.strides)
212
+ ):
213
+ raise ValueError(
214
+ "The sparse tensor representation (crow_indices(), col_indices(), and values() tensors) must be \
215
+ dense and contiguous."
216
+ )
217
+
218
+ values = wrapped.values.memory_buffer() # Typed memory viewed as a 1-D tensor.
219
+
220
+ num_dim = self.num_dimensions
221
+ num_sparse_dim = self.attr_name_map["num_sparse_dim"](tensor)
222
+ num_dense_dim = self.attr_name_map["num_dense_dim"](tensor)
223
+ num_batch_dim = num_dim - num_sparse_dim - num_dense_dim
224
+
225
+ if wrapped.block_order == "left" and num_batch_dim > 0:
226
+ raise ValueError("The 'left' block layout is not currently supported for batched BSR UST.")
227
+
228
+ block_size = wrapped.block_size
229
+ tensor_format = (
230
+ NamedFormats.BSRLeft(block_size)
231
+ if wrapped.block_order == "left"
232
+ else NamedFormats.BSRRightd(block_size, num_batch_dim, num_dense_dim)
233
+ )
234
+
235
+ # Check if the batch axes are in C-order for all component dense arrays.
236
+ if not (
237
+ check_monotonic_strides(wrapped.crow_indices.strides[:num_batch_dim], reverse=True)
238
+ and check_monotonic_strides(wrapped.col_indices.strides[:num_batch_dim], reverse=True)
239
+ and check_monotonic_strides(wrapped.values.strides[:num_batch_dim], reverse=True)
240
+ ):
241
+ raise ValueError(
242
+ "The batch dimensions in the sparse tensor representation (crow_indices(), col_indices(), \
243
+ and values() tensors) must use the C-layout."
244
+ )
245
+
246
+ # Create the UST.
247
+ ust = Tensor(tensor.shape, tensor_format=tensor_format, index_type=wrapped.index_type, dtype=wrapped.dtype)
248
+
249
+ ust._pos[num_batch_dim + 1] = wrapped.crow_indices
250
+ ust._crd[num_batch_dim + 1] = wrapped.col_indices
251
+ ust._val = values
252
+
253
+ return ust
254
+
255
+ def to_package(self):
256
+ """
257
+ This will create a sparse tensor for the original package from which this
258
+ interface was created.
259
+ """
260
+ create_bsr = self.attr_name_map["sparse_format_helper"].create_bsr
261
+ return create_bsr(self.shape, self.block_size, self.crow_indices, self.col_indices, self.values)
262
+
263
+ def release(self):
264
+ """
265
+ This method will release the wrapped tensor and any format-specific data
266
+ by setting them to None.
267
+ """
268
+ # The tensor reference.
269
+ self.tensor = None
270
+
271
+ # Format-specific data.
272
+ self._crow_indices = None
273
+ self._col_indices = None
274
+ self._values = None
275
+
276
+ def reset_unchecked(self, tensor):
277
+ """
278
+ This method will reset the wrapped tensor to the specified one, and update
279
+ any format-specific data accordingly. It assumes that all attributes
280
+ like the device, shape, etc are consistent between the existing and new tensor.
281
+
282
+ Args:
283
+ tensor: The native tensor to wrap.
284
+ """
285
+ # Update the tensor reference.
286
+ self.tensor = tensor
287
+
288
+ # Format-specific data.
289
+
290
+ if self.tensor_package == "nvmath":
291
+ # The data arrays are already wrapped.
292
+ self._crow_indices = self._attr_name_map["crow_indices"](tensor)
293
+ self._col_indices = self._attr_name_map["col_indices"](tensor)
294
+ self._values = self._attr_name_map["values"](tensor)
295
+ else:
296
+ wrapper = self._dense_tensorholder_type
297
+
298
+ crow_indices = self._attr_name_map["crow_indices"](tensor)
299
+ self._crow_indices = wrapper(crow_indices)
300
+
301
+ col_indices = self._attr_name_map["col_indices"](tensor)
302
+ self._col_indices = wrapper(col_indices)
303
+
304
+ values = self._attr_name_map["values"](tensor)
305
+ self._values = wrapper(values)
@@ -0,0 +1,256 @@
1
+ # Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ """
6
+ Interface to seamlessly use COO tensors from different libraries.
7
+ """
8
+
9
+ from __future__ import annotations # allows typehint of class methods to return the self class
10
+
11
+ __all__ = ["COOTensorHolder"]
12
+
13
+ from typing import Literal, TypeVar
14
+
15
+ from nvmath._internal.layout import is_contiguous_and_dense
16
+ from nvmath.internal import tensor_wrapper
17
+ from nvmath.internal.package_ifc import StreamHolder
18
+ from nvmath.internal.tensor_ifc import TensorHolder
19
+ from nvmath.internal.utils import infer_object_package
20
+
21
+ from .sparse_tensor_ifc import SparseTensorHolder
22
+
23
+ """
24
+ A generic type for the third-party COOTensor which a COOTensorHolder implementation wraps
25
+ around.
26
+ """
27
+ COOTensor = TypeVar("COOTensor")
28
+
29
+
30
+ class COOTensorHolder(SparseTensorHolder):
31
+ """
32
+ A simple wrapper type for COO sparse tensors to make the API package-agnostic. The
33
+ naming convention is sparse format name with the suffix "TensorHolder", which convention
34
+ is used in the sparse format helper.
35
+
36
+ Since the implementation is in terms of our dense tensor abstraction, package-specific
37
+ implementation is not needed.
38
+ """
39
+
40
+ _format_name: str = "COO"
41
+
42
+ def __init__(self, indices, values, *, attr_name_map=None, shape=None, tensor=None):
43
+ # tensor is the native tensor.
44
+ self.tensor = tensor
45
+
46
+ # attr_name_map is the canonical attribute name to package attribute name map.
47
+ # It is set when constructing from a tensor, otherwise it is None.
48
+ self._attr_name_map = attr_name_map
49
+
50
+ assert (shape is not None) ^ (tensor is not None), "Internal error."
51
+
52
+ if shape is not None:
53
+ self._shape = shape
54
+ else:
55
+ self._shape = tuple(tensor.shape)
56
+
57
+ # Wrap constituent dense tensors, if required. If it's a sequence, it will be
58
+ # a sequence of TensorHolder.
59
+ if not isinstance(indices, TensorHolder):
60
+ indices = [tensor_wrapper.wrap_operand(i) for i in indices]
61
+
62
+ if not isinstance(values, TensorHolder):
63
+ values = tensor_wrapper.wrap_operand(values)
64
+
65
+ # The wrapped constituent dense tensors.
66
+ self._indices = indices
67
+ self._values = values
68
+
69
+ # Ensure constituent dense tensors are all on the same device.
70
+ device_ids = {d.device_id for d in (*self._indices, self._values)}
71
+ message = f"Internal error: the arrays defining the sparse format aren't on the same device {device_ids}."
72
+ assert len(device_ids) == 1, message
73
+ self._device_id = device_ids.pop()
74
+
75
+ self._device = self._values.device
76
+
77
+ # Capture the native tensor package for use in reset_unchecked().
78
+ self.tensor_package = infer_object_package(self.tensor)
79
+
80
+ # The tensor holder type for the dense constituent tensors (take from values, since
81
+ # all constituent tensors have the same type).
82
+ self._dense_tensorholder_type = values.__class__
83
+
84
+ @classmethod
85
+ def create_from_tensor(cls, tensor, *, attr_name_map=None):
86
+ assert attr_name_map is not None, "Internal error."
87
+
88
+ # tensor is the native tensor.
89
+ # For UST, the buffers will be CuPy ndarrays.
90
+ indices = attr_name_map["indices"](tensor)
91
+ values = attr_name_map["values"](tensor)
92
+ return COOTensorHolder(indices, values, attr_name_map=attr_name_map, tensor=tensor)
93
+
94
+ @property
95
+ def attr_name_map(self):
96
+ return self._attr_name_map
97
+
98
+ @property
99
+ def device(self):
100
+ return self._device
101
+
102
+ @property
103
+ def device_id(self):
104
+ return self._device_id
105
+
106
+ @property
107
+ def dtype(self):
108
+ return self._values.dtype
109
+
110
+ @property
111
+ def index_type(self):
112
+ # TODO: check that all index arrays in the sequence have the same dtype.
113
+ return self._indices[0].dtype
114
+
115
+ @property
116
+ def format_name(self) -> str:
117
+ return COOTensorHolder._format_name
118
+
119
+ @property
120
+ def num_dimensions(self):
121
+ return len(self._shape)
122
+
123
+ @property
124
+ def shape(self):
125
+ return self._shape
126
+
127
+ @property
128
+ def indices(self):
129
+ """The TensorHolder object wrapping the indices array."""
130
+ return self._indices
131
+
132
+ @property
133
+ def values(self) -> TensorHolder:
134
+ """The TensorHolder object wrapping the values array."""
135
+ return self._values
136
+
137
+ def to(self, device_id: int | Literal["cpu"], stream_holder: StreamHolder | None):
138
+ """Copy the COOTensor representation to a different device.
139
+
140
+ No copy is performed if the COOTensor is already on the requested device.
141
+ """
142
+ if self.tensor_package == "nvmath":
143
+ return super().to(device_id=device_id, stream_holder=stream_holder)
144
+
145
+ target_indices = [i.to(device_id=device_id, stream_holder=stream_holder) for i in self.indices]
146
+ target_values = self.values.to(device_id=device_id, stream_holder=stream_holder)
147
+
148
+ return COOTensorHolder(target_indices, target_values, attr_name_map=self.attr_name_map, shape=self.shape)
149
+
150
+ def copy_(self, src, stream_holder: StreamHolder | None) -> None:
151
+ """Overwrite self.tensor (in-place) with a copy of src (COOTensor)."""
152
+
153
+ for c, component in enumerate(self.indices):
154
+ component.copy_(src=src.indices[c], stream_holder=stream_holder)
155
+ self.values.copy_(src=src.values, stream_holder=stream_holder)
156
+
157
+ def to_ust(self, *, stream):
158
+ from nvmath.sparse.ust.tensor import Tensor, _top_array
159
+ from nvmath.sparse.ust.tensor_format import NamedFormats
160
+
161
+ wrapped = self
162
+ tensor = wrapped.tensor
163
+ if not wrapped.attr_name_map["is_coalesced"](tensor):
164
+ raise ValueError(
165
+ "The COO tensor is not coalesced (metadata sorted with duplicates removed). \
166
+ To coalesce, use the operation provided by your sparse tensor library: `coalesce()`, `sum_duplicates()`, ..."
167
+ )
168
+
169
+ if not (
170
+ all(is_contiguous_and_dense(i.shape, i.strides) for i in self.indices)
171
+ and is_contiguous_and_dense(wrapped.values.shape, wrapped.values.strides)
172
+ ):
173
+ raise ValueError(
174
+ "The sparse tensor representation (indices() and values() tensors) must be \
175
+ dense and contiguous."
176
+ )
177
+
178
+ values = wrapped.values.memory_buffer() # Typed memory viewed as a 1-D tensor.
179
+
180
+ num_sparse_dim = self.attr_name_map["num_sparse_dim"](tensor)
181
+ num_dense_dim = self.attr_name_map["num_dense_dim"](tensor)
182
+ tensor_format = NamedFormats.COOd(num_sparse_dim, num_dense_dim)
183
+
184
+ # Check if the batch axes are in C-order for all component dense arrays.
185
+ if not all(i.strides == (1,) for i in wrapped.indices):
186
+ raise ValueError("The batch dimensions in the sparse tensor representation indices() must use the C-layout.")
187
+
188
+ # Create the UST.
189
+ ust = Tensor(tensor.shape, tensor_format=tensor_format, index_type=wrapped.index_type, dtype=wrapped.dtype)
190
+
191
+ dense_tensorholder_type = wrapped._dense_tensorholder_type
192
+ if wrapped.device_id == "cpu":
193
+ stream_holder = None
194
+ else:
195
+ from nvmath.internal import utils
196
+
197
+ stream_holder = utils.get_or_create_stream(wrapped.device_id, stream, dense_tensorholder_type.name)
198
+ ust._pos[0] = _top_array(
199
+ wrapped.indices[0].size,
200
+ dtype=wrapped.index_type,
201
+ device_id=wrapped.device_id,
202
+ dense_tensorholder_type=dense_tensorholder_type,
203
+ stream_holder=stream_holder,
204
+ )
205
+ for d in range(num_sparse_dim):
206
+ ust._crd[d] = wrapped.indices[d]
207
+ ust._val = values
208
+
209
+ return ust
210
+
211
+ def to_package(self):
212
+ """
213
+ This will create a sparse tensor for the original package from which this
214
+ interface was created.
215
+ """
216
+ create_coo = self.attr_name_map["sparse_format_helper"].create_coo
217
+ return create_coo(self.shape, self.indices, self.values)
218
+
219
+ def release(self):
220
+ """
221
+ This method will release the wrapped tensor and any format-specific data
222
+ by setting them to None.
223
+ """
224
+ # The tensor reference.
225
+ self.tensor = None
226
+
227
+ # Format-specific data.
228
+ self._indices = None
229
+ self._values = None
230
+
231
+ def reset_unchecked(self, tensor):
232
+ """
233
+ This method will reset the wrapped tensor to the specified one, and update
234
+ any format-specific data accordingly. It assumes that all attributes
235
+ like the device, shape, etc are consistent between the existing and new tensor.
236
+
237
+ Args:
238
+ tensor: The native tensor to wrap.
239
+ """
240
+ # Update the tensor reference.
241
+ self.tensor = tensor
242
+
243
+ # Format-specific data.
244
+
245
+ if self.tensor_package == "nvmath":
246
+ # The data arrays are already wrapped.
247
+ self._indices = self._attr_name_map["indices"](tensor)
248
+ self._values = self._attr_name_map["values"](tensor)
249
+ else:
250
+ wrapper = self._dense_tensorholder_type
251
+
252
+ indices = self._attr_name_map["indices"](tensor)
253
+ self._indices = [wrapper(i) for i in indices]
254
+
255
+ values = self._attr_name_map["values"](tensor)
256
+ self._values = wrapper(values)