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,382 @@
1
+ # Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from abc import ABC, abstractmethod
6
+
7
+ from nvmath.bindings import cusparse
8
+ from nvmath.bindings._internal.utils import FunctionNotFoundError
9
+ from nvmath.internal.typemaps import NAME_TO_DATA_TYPE
10
+
11
+ COMPATIBLE_SP_DN_PACKAGES = {("scipy", "numpy"), ("cupyx", "cupy"), ("torch", "torch"), ("nvmath", "nvmath")}
12
+
13
+ SUPPORTED_NAMED_FORMATS = {"BSR", "CSR", "CSC", "COO"}
14
+
15
+ INDEX_TYPE_MAP = {
16
+ "int32": cusparse.IndexType.INDEX_32I,
17
+ "int64": cusparse.IndexType.INDEX_64I,
18
+ "uint16": cusparse.IndexType.INDEX_16U,
19
+ }
20
+
21
+ ORDER_TYPE_MAP = {"left": cusparse.Order.COL, "right": cusparse.Order.ROW}
22
+
23
+ # The index base is always 0.
24
+ BASE = 0
25
+
26
+
27
+ class SparseIfc(ABC):
28
+ """
29
+ Abstract base to create and update sparse matrix descriptors.
30
+ """
31
+
32
+ @abstractmethod
33
+ def create(self):
34
+ """
35
+ Create a cuSPARSE matrix descriptor.
36
+ """
37
+ raise NotImplementedError
38
+
39
+ @abstractmethod
40
+ def update(self, new_operand):
41
+ """
42
+ Update the pointers in the sparse matrix descriptor.
43
+ """
44
+ raise NotImplementedError
45
+
46
+ # Destructor is not dependent on sparse or dense, so no abstraction is needed.
47
+
48
+
49
+ class COOIfc(SparseIfc):
50
+ """
51
+ Create and update sparse COO matrix descriptor.
52
+ """
53
+
54
+ def __init__(self, operand, layout_traits):
55
+ """
56
+ The operand must be a wrapped sparse tensor.
57
+ """
58
+ if layout_traits.batch_count != 1 or len(operand.indices) != 2:
59
+ raise NotImplementedError("Non-uniform batched COO matrices are not supported by cuSPARSE.")
60
+ self.values_size = operand.values.size
61
+ self.index_type = operand.index_type
62
+ self.dtype = operand.dtype
63
+ self.layout_traits = layout_traits
64
+ self.descriptor = None
65
+ # Updatable attributes
66
+ self.row_indices_data_ptr = operand.indices[0].data_ptr
67
+ self.col_indices_data_ptr = operand.indices[1].data_ptr
68
+ self.values_data_ptr = operand.values.data_ptr
69
+
70
+ def create(self):
71
+ """
72
+ Create a cuSPARSE COO matrix descriptor.
73
+ """
74
+ t = self.layout_traits
75
+ shape, nnz = t.mm_shape, self.values_size
76
+
77
+ if self.index_type not in INDEX_TYPE_MAP:
78
+ raise TypeError(f"The index type {self.index_type} is not in the supported types: {INDEX_TYPE_MAP.keys()}.")
79
+
80
+ index_type, value_type = INDEX_TYPE_MAP[self.index_type], NAME_TO_DATA_TYPE[self.dtype]
81
+
82
+ self.descriptor = cusparse.create_coo(
83
+ *shape,
84
+ nnz,
85
+ self.row_indices_data_ptr,
86
+ self.col_indices_data_ptr,
87
+ self.values_data_ptr,
88
+ index_type,
89
+ BASE,
90
+ value_type,
91
+ )
92
+
93
+ return self.descriptor
94
+
95
+ def update(self, new_operand):
96
+ """
97
+ Update the pointers in the sparse matrix descriptor.
98
+ """
99
+ self.row_indices_data_ptr = row_ptr = new_operand.indices[0].data_ptr
100
+ self.col_indices_data_ptr = col_ptr = new_operand.indices[1].data_ptr
101
+ self.values_data_ptr = values_data_ptr = new_operand.values.data_ptr
102
+ cusparse.coo_set_pointers(self.descriptor, row_ptr, col_ptr, values_data_ptr)
103
+
104
+
105
+ class CSRIfc(SparseIfc):
106
+ """
107
+ Create and update sparse CSR matrix descriptor.
108
+ """
109
+
110
+ # TODO: take logger to log debug messages.
111
+ def __init__(self, operand, layout_traits):
112
+ """
113
+ The operand must be a wrapped sparse tensor.
114
+ """
115
+ self.values_size = operand.values.size
116
+ self.crow_indices_size = operand.crow_indices.size
117
+ self.index_type = operand.index_type
118
+ self.dtype = operand.dtype
119
+ self.layout_traits = layout_traits
120
+ self.descriptor = None
121
+ # Updatable attributes
122
+ self.crow_indices_data_ptr = operand.crow_indices.data_ptr
123
+ self.col_indices_data_ptr = operand.col_indices.data_ptr
124
+ self.values_data_ptr = operand.values.data_ptr
125
+
126
+ def create(self):
127
+ """
128
+ Create a cuSPARSE CSR matrix descriptor.
129
+ """
130
+ t = self.layout_traits
131
+
132
+ if t.batch_broadcast:
133
+ shape, nnz = t.mm_shape, self.values_size
134
+ else:
135
+ assert self.values_size % t.batch_count == 0, "Internal error."
136
+ shape, nnz = t.mm_shape, self.values_size // t.batch_count
137
+
138
+ if self.index_type not in INDEX_TYPE_MAP:
139
+ raise TypeError(f"The index type {self.index_type} is not in the supported types: {INDEX_TYPE_MAP.keys()}.")
140
+
141
+ index_type, value_type = INDEX_TYPE_MAP[self.index_type], NAME_TO_DATA_TYPE[self.dtype]
142
+
143
+ self.descriptor = cusparse.create_csr(
144
+ *shape,
145
+ nnz,
146
+ self.crow_indices_data_ptr,
147
+ self.col_indices_data_ptr,
148
+ self.values_data_ptr,
149
+ index_type,
150
+ index_type,
151
+ BASE,
152
+ value_type,
153
+ )
154
+
155
+ # Handle batching.
156
+ if t.batch_count > 1:
157
+ if t.batch_broadcast:
158
+ crow_indices_batch_offset = 0
159
+ values_batch_offset = 0
160
+ else:
161
+ assert self.crow_indices_size % t.batch_count == 0, "Internal error."
162
+ crow_indices_batch_offset = self.crow_indices_size // t.batch_count
163
+
164
+ assert self.values_size % t.batch_count == 0, "Internal error."
165
+ values_batch_offset = self.values_size // t.batch_count
166
+
167
+ cusparse.csr_set_strided_batch(self.descriptor, t.batch_count, crow_indices_batch_offset, values_batch_offset)
168
+
169
+ return self.descriptor
170
+
171
+ def update(self, new_operand):
172
+ """
173
+ Update the pointers in the sparse matrix descriptor.
174
+ """
175
+ self.crow_indices_data_ptr = new_operand.crow_indices.data_ptr
176
+ self.col_indices_data_ptr = new_operand.col_indices.data_ptr
177
+ self.values_data_ptr = new_operand.values.data_ptr
178
+ cusparse.csr_set_pointers(self.descriptor, self.crow_indices_data_ptr, self.col_indices_data_ptr, self.values_data_ptr)
179
+
180
+
181
+ class BSRIfc(SparseIfc):
182
+ """
183
+ Create and update sparse BSR matrix descriptor.
184
+ """
185
+
186
+ # TODO: take logger to log debug messages.
187
+ def __init__(self, operand, layout_traits):
188
+ """
189
+ The operand must be a wrapped sparse tensor.
190
+ """
191
+ self.block_size = operand.block_size
192
+ self.values_size = operand.values.size
193
+ self.crow_indices_size = operand.crow_indices.size
194
+ self.col_indices_size = operand.col_indices.size
195
+ self.index_type = operand.index_type
196
+ self.dtype = operand.dtype
197
+ self.block_order = ORDER_TYPE_MAP[operand.block_order]
198
+ self.layout_traits = layout_traits
199
+ self.descriptor = None
200
+ # Updatable attributes
201
+ self.crow_indices_data_ptr = operand.crow_indices.data_ptr
202
+ self.col_indices_data_ptr = operand.col_indices.data_ptr
203
+ self.values_data_ptr = operand.values.data_ptr
204
+
205
+ def create(self):
206
+ """
207
+ Create a cuSPARSE BSR matrix descriptor.
208
+ """
209
+ t = self.layout_traits
210
+ b0, b1 = self.block_size
211
+
212
+ # TODO: more elegant way of getting the number of non-zero blocks.
213
+ if t.batch_broadcast:
214
+ shape, bnnz = t.mm_shape, self.values_size // (b0 * b1)
215
+ else:
216
+ assert self.values_size % t.batch_count == 0, "Internal error."
217
+ shape, bnnz = t.mm_shape, self.values_size // (t.batch_count * b0 * b1)
218
+
219
+ assert shape[0] % b0 == 0 and shape[1] % b1 == 0, "Internal error."
220
+ shape_in_blocks = shape[0] // b0, shape[1] // b1
221
+
222
+ if self.index_type not in INDEX_TYPE_MAP:
223
+ raise TypeError(f"The index type {self.index_type} is not in the supported types: {INDEX_TYPE_MAP.keys()}.")
224
+
225
+ index_type, value_type = INDEX_TYPE_MAP[self.index_type], NAME_TO_DATA_TYPE[self.dtype]
226
+
227
+ try:
228
+ self.descriptor = cusparse.create_bsr(
229
+ *shape_in_blocks,
230
+ bnnz,
231
+ b0,
232
+ b1,
233
+ self.crow_indices_data_ptr,
234
+ self.col_indices_data_ptr,
235
+ self.values_data_ptr,
236
+ index_type,
237
+ index_type,
238
+ BASE,
239
+ value_type,
240
+ self.block_order,
241
+ )
242
+ except FunctionNotFoundError as e:
243
+ raise RuntimeError("BSR is not supported by the installed cuSPARSE library.") from e
244
+
245
+ # Handle batching.
246
+ if t.batch_count > 1:
247
+ if t.batch_broadcast:
248
+ crow_indices_batch_offset = 0
249
+ col_indices_batch_offset = 0
250
+ values_batch_offset = 0
251
+ else:
252
+ assert self.crow_indices_size % t.batch_count == 0, "Internal error."
253
+ crow_indices_batch_offset = self.crow_indices_size // t.batch_count
254
+
255
+ assert self.col_indices_size % t.batch_count == 0, "Internal error."
256
+ col_indices_batch_offset = self.col_indices_size // t.batch_count
257
+
258
+ assert self.values_size % t.batch_count == 0, "Internal error."
259
+ values_batch_offset = self.values_size // t.batch_count
260
+
261
+ cusparse.bsr_set_strided_batch(
262
+ self.descriptor, t.batch_count, crow_indices_batch_offset, col_indices_batch_offset, values_batch_offset
263
+ )
264
+
265
+ return self.descriptor
266
+
267
+ def update(self, new_operand):
268
+ """
269
+ Update the pointers in the sparse matrix descriptor.
270
+ """
271
+ self.crow_indices_data_ptr = new_operand.crow_indices.data_ptr
272
+ self.col_indices_data_ptr = new_operand.col_indices.data_ptr
273
+ self.values_data_ptr = new_operand.values.data_ptr
274
+
275
+ # There is no API currently to just update the pointers so we've to create a new
276
+ # descriptor.
277
+ if self.descriptor is not None:
278
+ cusparse.destroy_sp_mat(self.descriptor)
279
+ self.create()
280
+
281
+
282
+ class CSCIfc(SparseIfc):
283
+ """
284
+ Create and update sparse CSC matrix descriptor.
285
+ """
286
+
287
+ # TODO: take logger to log debug messages.
288
+ def __init__(self, operand, layout_traits):
289
+ """
290
+ The operand must be a wrapped sparse tensor.
291
+ """
292
+ self.values_size = operand.values.size
293
+ self.index_type = operand.index_type
294
+ self.dtype = operand.dtype
295
+ self.layout_traits = layout_traits
296
+ self.descriptor = None
297
+
298
+ # Updatable attributes
299
+ self.ccol_indices_data_ptr = operand.ccol_indices.data_ptr
300
+ self.row_indices_data_ptr = operand.row_indices.data_ptr
301
+ self.values_data_ptr = operand.values.data_ptr
302
+
303
+ def create(self):
304
+ """
305
+ Create a cuSPARSE CSC matrix descriptor.
306
+ """
307
+ t = self.layout_traits
308
+
309
+ if t.batch_broadcast:
310
+ shape, nnz = t.mm_shape, self.values_size
311
+ else:
312
+ assert self.values_size % t.batch_count == 0, "Internal error."
313
+ shape, nnz = t.mm_shape, self.values_size // t.batch_count
314
+
315
+ if self.index_type not in INDEX_TYPE_MAP:
316
+ raise TypeError(f"The index type {self.index_type} is not in the supported types: {INDEX_TYPE_MAP.keys()}.")
317
+
318
+ index_type, value_type = INDEX_TYPE_MAP[self.index_type], NAME_TO_DATA_TYPE[self.dtype]
319
+
320
+ self.descriptor = cusparse.create_csc(
321
+ *shape,
322
+ nnz,
323
+ self.ccol_indices_data_ptr,
324
+ self.row_indices_data_ptr,
325
+ self.values_data_ptr,
326
+ index_type,
327
+ index_type,
328
+ BASE,
329
+ value_type,
330
+ )
331
+
332
+ # Handle batching.
333
+ if t.batch_count > 1:
334
+ raise NotImplementedError("The cuSPARSE library doesn't currently support batched CSC matrices.")
335
+
336
+ return self.descriptor
337
+
338
+ def update(self, new_operand):
339
+ """
340
+ Update the pointers in the sparse matrix descriptor.
341
+ """
342
+ self.ccol_indices_data_ptr = ccol_indices_data_ptr = new_operand.ccol_indices.data_ptr
343
+ self.row_indices_data_ptr = row_indices_data_ptr = new_operand.row_indices.data_ptr
344
+ self.values_data_ptr = values_data_ptr = new_operand.values.data_ptr
345
+ cusparse.csc_set_pointers(self.descriptor, ccol_indices_data_ptr, row_indices_data_ptr, values_data_ptr)
346
+
347
+
348
+ class DenseMatrixIfc:
349
+ """
350
+ Create and update dense matrix descriptors.
351
+ """
352
+
353
+ def __init__(self, operand, layout_traits):
354
+ """
355
+ The operand must be a wrapped dense tensor.
356
+ """
357
+ self.dtype = operand.dtype
358
+ self.layout_traits = layout_traits
359
+ self.descriptor = None
360
+ # Updatable attributes
361
+ self.data_ptr = operand.data_ptr
362
+
363
+ def create(self):
364
+ """
365
+ Create a cuSPARSE dense matrix descriptor.
366
+ """
367
+
368
+ t = self.layout_traits
369
+
370
+ self.descriptor = cusparse.create_dn_mat(*t.mm_shape, t.ld, self.data_ptr, NAME_TO_DATA_TYPE[self.dtype], t.order)
371
+
372
+ if t.batch_count > 1:
373
+ cusparse.dn_mat_set_strided_batch(self.descriptor, t.batch_count, t.batch_offset)
374
+
375
+ return self.descriptor
376
+
377
+ def update(self, new_operand):
378
+ """
379
+ Update the pointers in the dense matrix descriptor.
380
+ """
381
+ self.data_ptr = data_ptr = new_operand.data_ptr
382
+ cusparse.dn_mat_set_values(self.descriptor, data_ptr)
@@ -0,0 +1,303 @@
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 BSC tensors from different libraries.
7
+ """
8
+
9
+ from __future__ import annotations # allows typehint of class methods to return the self class
10
+
11
+ __all__ = ["BSCTensorHolder"]
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 BSCTensor which a BSCTensorHolder implementation wraps
25
+ around.
26
+ """
27
+ BSCTensor = TypeVar("BSCTensor")
28
+
29
+
30
+ class BSCTensorHolder(SparseTensorHolder):
31
+ """
32
+ A simple wrapper type for BSC 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 = "BSC"
41
+
42
+ def __init__(
43
+ self, block_size, block_order, ccol_indices, row_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(ccol_indices, TensorHolder):
67
+ ccol_indices = tensor_wrapper.wrap_operand(ccol_indices)
68
+
69
+ if not isinstance(row_indices, TensorHolder):
70
+ row_indices = tensor_wrapper.wrap_operand(row_indices)
71
+
72
+ if not isinstance(values, TensorHolder):
73
+ values = tensor_wrapper.wrap_operand(values)
74
+
75
+ # The wrapped constituent dense tensors.
76
+ self._ccol_indices = ccol_indices
77
+ self._row_indices = row_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._ccol_indices, self._row_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
+ ccol_indices = attr_name_map["ccol_indices"](tensor)
104
+ row_indices = attr_name_map["row_indices"](tensor)
105
+ values = attr_name_map["values"](tensor)
106
+ return BSCTensorHolder(
107
+ block_size, block_order, ccol_indices, row_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._ccol_indices.dtype
129
+
130
+ @property
131
+ def format_name(self) -> str:
132
+ return BSCTensorHolder._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 ccol_indices(self) -> TensorHolder:
152
+ """The TensorHolder object wrapping the ccol_indices array."""
153
+ return self._ccol_indices
154
+
155
+ @property
156
+ def row_indices(self) -> TensorHolder:
157
+ """The TensorHolder object wrapping the row_indices array."""
158
+ return self._row_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 BSCTensor representation to a different device.
167
+
168
+ No copy is performed if the BSCTensor is already on the requested device.
169
+ """
170
+
171
+ if self.tensor_package == "nvmath":
172
+ return super().to(device_id=device_id, stream_holder=stream_holder)
173
+
174
+ target_ccol_indices = self.ccol_indices.to(device_id=device_id, stream_holder=stream_holder)
175
+ target_row_indices = self.row_indices.to(device_id=device_id, stream_holder=stream_holder)
176
+ target_values = self.values.to(device_id=device_id, stream_holder=stream_holder)
177
+
178
+ return BSCTensorHolder(
179
+ self.block_size,
180
+ self.block_order,
181
+ target_ccol_indices,
182
+ target_row_indices,
183
+ target_values,
184
+ attr_name_map=self.attr_name_map,
185
+ shape=self.shape,
186
+ )
187
+
188
+ def copy_(self, src, stream_holder: StreamHolder | None) -> None:
189
+ """Overwrite self.tensor (in-place) with a copy of src (BSCTensor)."""
190
+
191
+ self._block_size = src.block_size
192
+ self._block_order = src.block_order
193
+ self.ccol_indices.copy_(src=src.ccol_indices, stream_holder=stream_holder)
194
+ self.row_indices.copy_(src=src.row_indices, stream_holder=stream_holder)
195
+ self.values.copy_(src=src.values, stream_holder=stream_holder)
196
+
197
+ def to_ust(self, *, stream):
198
+ from nvmath.sparse.ust.tensor import Tensor
199
+ from nvmath.sparse.ust.tensor_format import NamedFormats
200
+
201
+ wrapped = self
202
+ tensor = wrapped.tensor
203
+ if not (wrapped.attr_name_map["is_coalesced"](tensor) and wrapped.attr_name_map["has_sorted_indices"](tensor)):
204
+ raise ValueError(
205
+ "The BSC tensor is not coalesced (metadata sorted with duplicates removed). \
206
+ To coalesce, use the operation provided by your sparse tensor library: `coalesce()`, `sum_duplicates()`, ..."
207
+ )
208
+
209
+ if not (
210
+ is_contiguous_and_dense(wrapped.ccol_indices.shape, wrapped.ccol_indices.strides)
211
+ and is_contiguous_and_dense(wrapped.row_indices.shape, wrapped.row_indices.strides)
212
+ and is_contiguous_and_dense(wrapped.values.shape, wrapped.values.strides)
213
+ ):
214
+ raise ValueError(
215
+ "The sparse tensor representation (ccol_indices(), row_indices(), and values() tensors) must be \
216
+ dense and contiguous."
217
+ )
218
+
219
+ values = wrapped.values.memory_buffer() # Typed memory viewed as a 1-D tensor.
220
+
221
+ num_dim = self.num_dimensions
222
+ num_sparse_dim = self.attr_name_map["num_sparse_dim"](tensor)
223
+ num_dense_dim = self.attr_name_map["num_dense_dim"](tensor)
224
+ num_batch_dim = num_dim - num_sparse_dim - num_dense_dim
225
+
226
+ block_size = wrapped.block_size
227
+ tensor_format = (
228
+ NamedFormats.BSCLeftd(block_size, num_batch_dim, num_dense_dim)
229
+ if wrapped.block_order == "left"
230
+ else NamedFormats.BSCRightd(block_size, num_batch_dim, num_dense_dim)
231
+ )
232
+
233
+ # Check if the batch axes are in C-order for all component dense arrays.
234
+ if not (
235
+ check_monotonic_strides(wrapped.ccol_indices.strides[:num_batch_dim], reverse=True)
236
+ and check_monotonic_strides(wrapped.row_indices.strides[:num_batch_dim], reverse=True)
237
+ and check_monotonic_strides(wrapped.values.strides[:num_batch_dim], reverse=True)
238
+ ):
239
+ raise ValueError(
240
+ "The batch dimensions in the sparse tensor representation (ccol_indices(), row_indices(), \
241
+ and values() tensors) must use the C-layout."
242
+ )
243
+
244
+ # Create the UST.
245
+ ust = Tensor(tensor.shape, tensor_format=tensor_format, index_type=wrapped.index_type, dtype=wrapped.dtype)
246
+
247
+ ust._pos[num_batch_dim + 1] = wrapped.ccol_indices
248
+ ust._crd[num_batch_dim + 1] = wrapped.row_indices
249
+ ust._val = values
250
+
251
+ return ust
252
+
253
+ def to_package(self):
254
+ """
255
+ This will create a sparse tensor for the original package from which this
256
+ interface was created.
257
+ """
258
+ create_bsc = self.attr_name_map["sparse_format_helper"].create_bsc
259
+ return create_bsc(self.shape, self.block_size, self.ccol_indices, self.row_indices, self.values)
260
+
261
+ def release(self):
262
+ """
263
+ This method will release the wrapped tensor and any format-specific data
264
+ by setting them to None.
265
+ """
266
+ # The tensor reference.
267
+ self.tensor = None
268
+
269
+ # Format-specific data.
270
+ self._ccol_indices = None
271
+ self._row_indices = None
272
+ self._values = None
273
+
274
+ def reset_unchecked(self, tensor):
275
+ """
276
+ This method will reset the wrapped tensor to the specified one, and update
277
+ any format-specific data accordingly. It assumes that all attributes
278
+ like the device, shape, etc are consistent between the existing and new tensor.
279
+
280
+ Args:
281
+ tensor: The native tensor to wrap.
282
+ """
283
+ # Update the tensor reference.
284
+ self.tensor = tensor
285
+
286
+ # Format-specific data.
287
+
288
+ if self.tensor_package == "nvmath":
289
+ # The data arrays are already wrapped.
290
+ self._ccol_indices = self._attr_name_map["ccol_indices"](tensor)
291
+ self._row_indices = self._attr_name_map["row_indices"](tensor)
292
+ self._values = self._attr_name_map["values"](tensor)
293
+ else:
294
+ wrapper = self._dense_tensorholder_type
295
+
296
+ ccol_indices = self._attr_name_map["ccol_indices"](tensor)
297
+ self._ccol_indices = wrapper(ccol_indices)
298
+
299
+ row_indices = self._attr_name_map["row_indices"](tensor)
300
+ self._row_indices = wrapper(row_indices)
301
+
302
+ values = self._attr_name_map["values"](tensor)
303
+ self._values = wrapper(values)