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,7 @@
1
+ # Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from . import interfaces as interfaces
6
+ from .tensor import * # noqa: F403
7
+ from .tensor_format import * # noqa: F403
@@ -0,0 +1,422 @@
1
+ # Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ """
6
+ This module implements converters for the Universal Sparse Tensor (UST).
7
+ """
8
+
9
+ __all__ = []
10
+
11
+ from collections.abc import Sequence
12
+
13
+ # from numba import njit
14
+ import numpy as np
15
+
16
+ from nvmath.internal import utils
17
+ from nvmath.internal.tensor_wrapper import wrap_operand
18
+
19
+ from ._utils import LevelMap, np_enveloping_type, resolve_stream, stream_context
20
+ from .tensor_format import Add, LevelExpr, LevelFormat, Subtract, is_unique
21
+
22
+
23
+ class TensorDecomposer:
24
+ """
25
+ A class that traverses a Universal Sparse Tensor and calls a functor for every
26
+ stored element. The traversal can be used for conversions and debugging but may
27
+ not necessarily provide the most efficient way of implementing a traversal.
28
+ Also see set_kernel and run_kernel.
29
+
30
+ Args:
31
+ tensor: the UST tensor for traversal
32
+ functor: a function of the form `def visit(dims, val)`
33
+ """
34
+
35
+ def __init__(self, tensor, functor):
36
+ self._tensor = tensor
37
+ self._functor = functor
38
+ self._flist = list(tensor.tensor_format.levels.items())
39
+ self._lvls = [0] * tensor.num_levels # pre-populate
40
+
41
+ def run(self, stream=None):
42
+ # We're going to repeatedly access single items of the tensor, so it's
43
+ # more efficient to copy to CPU first.
44
+ if self._tensor.device_id != "cpu":
45
+ stream_holder = resolve_stream(stream, self._tensor)
46
+ self._tensor = self._tensor._to("cpu", stream_holder)
47
+ self._iterate(0, 0, None)
48
+
49
+ def _iterate(self, idx, p, lasta):
50
+ # All levels exhausted?
51
+ if idx == self._tensor.num_levels:
52
+ assert lasta is None # consumed add/sub in range
53
+ val = self._tensor._val.tensor
54
+ self._functor(self._tensor.tensor_format.lvl2dim(self._lvls), val[p].item())
55
+ return
56
+ # Inspect level.
57
+ k, v = self._flist[idx]
58
+ if isinstance(v, Sequence):
59
+ fmt, prop = v
60
+ else:
61
+ fmt, prop = v, None
62
+ # Handle level format.
63
+ if fmt in (LevelFormat.DENSE, LevelFormat.BATCH):
64
+ sz = self._tensor.levels[idx]
65
+ for i in range(sz):
66
+ self._lvls[idx] = i
67
+ self._iterate(idx + 1, p * sz + i, lasta)
68
+ elif fmt == LevelFormat.COMPRESSED:
69
+ if isinstance(k, LevelExpr) and isinstance(k.operator, (Add, Subtract)):
70
+ assert lasta is None # no add/sub nesting
71
+ lasta = idx # record last add/sub
72
+ pos = self._tensor._pos[idx].tensor
73
+ crd = self._tensor._crd[idx].tensor
74
+ assert pos.ndim == crd.ndim
75
+ adjust = 0
76
+ if pos.ndim > 1:
77
+ # This only happens for prior BATCH. Correct the higher-dimensions in
78
+ # both pos and crd buffers and adjust position by #nnz per batch.
79
+ assert pos.ndim == idx
80
+ for i in range(idx - 1):
81
+ assert self._flist[i][1] == LevelFormat.BATCH
82
+ pos = pos[self._lvls[i]]
83
+ crd = crd[self._lvls[i]]
84
+ adjust = pos[-1].item() * (p - self._lvls[idx - 1]) // self._tensor.levels[idx - 1]
85
+ p = self._lvls[idx - 1]
86
+ lo = pos[p].item()
87
+ hi = pos[p + 1].item()
88
+ for i in range(lo, hi):
89
+ self._lvls[idx] = crd[i].item()
90
+ self._iterate(idx + 1, i + adjust, lasta)
91
+ elif fmt == LevelFormat.SINGLETON:
92
+ crd = self._tensor._crd[idx].tensor
93
+ assert crd.ndim == 1
94
+ self._lvls[idx] = crd[p].item()
95
+ self._iterate(idx + 1, p, lasta)
96
+ elif fmt == LevelFormat.RANGE:
97
+ assert lasta is not None # single add/sub-range relation
98
+ add, _ = self._flist[lasta]
99
+ isI = k == add.expression2
100
+ di = self._tensor.tensor_format.dimensions.index(k)
101
+ dj = self._tensor.tensor_format.dimensions.index(add.expression1 if isI else add.expression2)
102
+ szi = self._tensor.extents[di]
103
+ szj = self._tensor.extents[dj]
104
+ lsz = self._lvls[lasta]
105
+ if isinstance(add.operator, Add):
106
+ off = lsz
107
+ lo = max(0, off - szj + 1)
108
+ hi = min(szi, off + 1)
109
+ else:
110
+ off = -lsz if isI else lsz
111
+ lo = max(0, off)
112
+ hi = min(szi, szj + off)
113
+ for i in range(lo, hi):
114
+ self._lvls[idx] = i
115
+ self._iterate(idx + 1, p * szi + i, None)
116
+ elif fmt == LevelFormat.DELTA:
117
+ assert is_unique(prop)
118
+ pos = self._tensor._pos[idx].tensor
119
+ crd = self._tensor._crd[idx].tensor
120
+ assert pos.ndim == 1 and crd.ndim == 1
121
+ corig = 0
122
+ lo = pos[p].item()
123
+ hi = pos[p + 1].item()
124
+ for i in range(lo, hi):
125
+ corig += crd[i].item()
126
+ self._lvls[idx] = corig
127
+ self._iterate(idx + 1, i, lasta)
128
+ corig += 1
129
+ elif fmt == LevelFormat.STRUCTURED:
130
+ assert isinstance(prop, int) # n is the property
131
+ crd = self._tensor._crd[idx].tensor
132
+ assert crd.ndim == 1
133
+ lo = p * prop
134
+ hi = lo + prop
135
+ for i in range(lo, hi):
136
+ self._lvls[idx] = crd[i].item()
137
+ self._iterate(idx + 1, i, lasta)
138
+ else:
139
+ raise AssertionError(f"Unsupported: {fmt}")
140
+
141
+
142
+ class TensorComposer:
143
+ """
144
+ A class to build a Universal Sparse Tensor from a coordinate list. This is a convenience
145
+ class for composing UST objects, expected to run on the host, and does not necessarily
146
+ provide the most efficient way of building a UST. Since the builder takes unordered
147
+ dimension indices together with values, it can also be function as intermediate step
148
+ for tensor format conversions.
149
+
150
+ Args:
151
+ source: source tensor
152
+ target: target tensor
153
+ indices: a 2-dim array of shape (dim,nse) with dimension indices (on CPU)
154
+ values: a 1-dim array of shape (nse,) with the stored numerical values (on CPU)
155
+ is_sorted: whether coordinate list is lexicographically sorted
156
+ """
157
+
158
+ def __init__(self, source, target, indices, values, is_sorted=False):
159
+ assert len(indices.shape) == 2 and len(values.shape) == 1, "Internal error."
160
+ fmt = target.tensor_format
161
+ dim, nse = indices.shape
162
+ assert dim == fmt.num_dimensions and nse == values.shape[0]
163
+ lvl = fmt.num_levels
164
+ # Translate dimension indices to level indices.
165
+ if not fmt.is_identity:
166
+ lindices = np.zeros((lvl, nse), dtype=indices.dtype)
167
+ for i in range(nse):
168
+ lindices[:, i] = fmt.dim2lvl(indices[:, i])
169
+ indices = lindices
170
+ is_sorted = False
171
+ # Apply lexicographical sort on level indices.
172
+ if not is_sorted:
173
+ sorted_indices = np.lexsort(indices[::-1])
174
+ indices = indices[:, sorted_indices]
175
+ values = values[sorted_indices]
176
+ # Bookkeeping.
177
+ self._source = source
178
+ self._target = target
179
+ self._lvl = lvl
180
+ self._flist = list(fmt.levels.values())
181
+ self._indices = indices
182
+ self._values = values
183
+ self._pos_sz = np.zeros((lvl,), dtype=indices.dtype)
184
+ self._crd_sz = np.zeros((lvl,), dtype=indices.dtype)
185
+ self._val_sz = 0
186
+
187
+ def run(self, stream=None):
188
+ dim, nse = self._indices.shape
189
+
190
+ # Scan data to find sizes. Note that for some forms (like COO and CSR), all sizes
191
+ # can easily be computed deterministically without a first scan. For simplicity,
192
+ # we use the scan for both analysis and insertion, however.
193
+ self._insert_builder(0, lo=0, hi=nse, is_insert=False)
194
+
195
+ # Pre-allocate and reset sizes.
196
+ package = self._source._dense_tensorholder_type
197
+ device_id = self._source.device_id # no device migration in convert()
198
+ stream_holder = resolve_stream(stream, self._source)
199
+ self._pos = LevelMap()
200
+ self._crd = LevelMap()
201
+ for idx in range(self._lvl):
202
+ self._pos[idx] = utils.create_empty_tensor(
203
+ package,
204
+ extents=(self._pos_sz[idx],),
205
+ dtype=self._target.index_type,
206
+ device_id=device_id,
207
+ stream_holder=stream_holder,
208
+ verify_strides=False,
209
+ )
210
+ self._pos_sz[idx] = 0
211
+ self._crd[idx] = utils.create_empty_tensor(
212
+ package,
213
+ extents=(self._crd_sz[idx],),
214
+ dtype=self._target.index_type,
215
+ device_id=device_id,
216
+ stream_holder=stream_holder,
217
+ verify_strides=False,
218
+ )
219
+ self._crd_sz[idx] = 0
220
+ self._val = utils.create_empty_tensor(
221
+ package,
222
+ extents=(self._val_sz,),
223
+ dtype=self._target.dtype,
224
+ device_id=device_id,
225
+ stream_holder=stream_holder,
226
+ verify_strides=False,
227
+ )
228
+ self._val_sz = 0
229
+
230
+ # Scan to perform the actual insertion.
231
+ with stream_context(stream_holder):
232
+ self._insert_builder(0, lo=0, hi=nse, is_insert=True)
233
+ return (self._pos, self._crd, self._val)
234
+
235
+ def _insert_builder(self, idx, lo, hi, is_insert):
236
+ # All levels exhausted?
237
+ if idx == self._lvl:
238
+ assert lo < hi
239
+ self._append_val(self._values[lo].item(), 1, is_insert)
240
+ return
241
+ # Handle segments.
242
+ fmt = self._get_format(idx)
243
+ rng = hi - lo
244
+ full = 0
245
+ while lo < hi:
246
+ # Find segment.
247
+ crd = self._indices[idx][lo]
248
+ seg = lo + 1
249
+ if is_unique(self._get_prop(idx)):
250
+ while seg < hi and self._indices[idx][seg] == crd:
251
+ seg += 1
252
+ # Handle level format.
253
+ if fmt in (LevelFormat.DENSE, LevelFormat.RANGE):
254
+ assert crd >= full
255
+ if crd > full:
256
+ self._segment_builder(idx + 1, 0, crd - full, is_insert)
257
+ elif fmt in (LevelFormat.COMPRESSED, LevelFormat.SINGLETON):
258
+ self._append_crd(idx, crd, 1, is_insert)
259
+ elif fmt == LevelFormat.DELTA:
260
+ d = self._get_prop(idx)
261
+ assert isinstance(d, int)
262
+ mDelta = (1 << d) - 1
263
+ delta = crd - full
264
+ while delta > mDelta:
265
+ self._append_crd(idx, mDelta, 1, is_insert)
266
+ self._append_val(0, 1, is_insert)
267
+ delta -= mDelta + 1
268
+ self._append_crd(idx, delta, 1, is_insert)
269
+ elif fmt == LevelFormat.STRUCTURED:
270
+ # Pre-correction of N:M strip.
271
+ n = self._get_prop(idx)
272
+ if rng > n:
273
+ raise AssertionError(f"Not structured: more than {n} nonzero elements in a strip")
274
+ while rng < n and full < crd:
275
+ self._append_crd(idx, full, 1, is_insert)
276
+ self._append_val(0, 1, is_insert)
277
+ rng += 1
278
+ full += 1
279
+ self._append_crd(idx, crd, 1, is_insert) # strip insertion
280
+ else:
281
+ # TODO: BATCH
282
+ raise NotImplementedError(f"Unsupported: {fmt}")
283
+ full = crd + 1
284
+ self._insert_builder(idx + 1, lo, seg, is_insert)
285
+ lo = seg # next segment
286
+ # Post-correction of N:M strip.
287
+ if fmt == LevelFormat.STRUCTURED:
288
+ n = self._get_prop(idx)
289
+ if rng > n:
290
+ raise AssertionError(f"Not structured: more than {n} nonzero elements in a strip")
291
+ while rng < n:
292
+ self._append_crd(idx, full, 1, is_insert)
293
+ self._append_val(0, 1, is_insert)
294
+ rng += 1
295
+ full += 1
296
+ # Done with segments.
297
+ self._segment_builder(idx, full, 1, is_insert)
298
+
299
+ def _segment_builder(self, idx, full, repeat, is_insert):
300
+ # All levels exhausted?
301
+ if idx == self._lvl:
302
+ self._append_val(0, repeat, is_insert)
303
+ return
304
+ # Handle level format.
305
+ fmt = self._get_format(idx)
306
+ if fmt in (LevelFormat.DENSE, LevelFormat.RANGE):
307
+ sz = self._target.levels[idx]
308
+ assert sz >= full
309
+ self._segment_builder(idx + 1, 0, repeat * (sz - full), is_insert)
310
+ elif fmt in (LevelFormat.COMPRESSED, LevelFormat.DELTA):
311
+ self._append_pos(idx, self._crd_sz[idx], repeat, is_insert)
312
+ elif fmt == LevelFormat.SINGLETON:
313
+ # TODO: ELL
314
+ pass # nothing to do for singleton
315
+ elif fmt == LevelFormat.STRUCTURED:
316
+ # Correction for all N:M strips that were completely missed.
317
+ if full == 0:
318
+ n = self._get_prop(idx)
319
+ for _r in range(repeat):
320
+ for c in range(n):
321
+ self._append_crd(idx, c, 1, is_insert)
322
+ self._append_val(0, 1, is_insert)
323
+ else:
324
+ # TODO: BATCH
325
+ raise NotImplementedError(f"Unsupported: {fmt}")
326
+
327
+ def _append_pos(self, idx, pos, repeat, is_insert):
328
+ if self._pos_sz[idx] == 0: # append initial 0 at start
329
+ if is_insert:
330
+ self._pos[idx].tensor[0] = 0
331
+ self._pos_sz[idx] = 1
332
+ if is_insert:
333
+ start = self._pos_sz[idx]
334
+ self._pos[idx].tensor[start : start + repeat] = pos
335
+ self._pos_sz[idx] += repeat
336
+
337
+ def _append_crd(self, idx, crd, repeat, is_insert):
338
+ if is_insert:
339
+ start = self._crd_sz[idx]
340
+ self._crd[idx].tensor[start : start + repeat] = crd
341
+ self._crd_sz[idx] += repeat
342
+
343
+ def _append_val(self, val, repeat, is_insert):
344
+ if is_insert:
345
+ start = self._val_sz
346
+ self._val.tensor[start : start + repeat] = val
347
+ self._val_sz += repeat
348
+
349
+ def _get_format(self, idx):
350
+ f = self._flist[idx]
351
+ return f[0] if isinstance(f, tuple) else f
352
+
353
+ def _get_prop(self, idx):
354
+ f = self._flist[idx]
355
+ return f[1] if isinstance(f, tuple) else None
356
+
357
+
358
+ class TensorConverter:
359
+ """
360
+ Converts a tensor from one format to another (using the [de]composer). The tensor
361
+ converter reduces the O(n^2) conversion problem into a O(n) problem by using a
362
+ [de]composer that converts to an intermediate coordinate list on the CPU first.
363
+ This class is provided to enable conversions between any UST formats. However,
364
+ this does not necessarily provide the most efficient way of implementing a
365
+ conversion. Fast paths (or library dispatches) can be used for efficiency.
366
+
367
+ CSR\\ //CSR
368
+ CSC \\ // CSC
369
+ UST ... > COO < ... UST
370
+ ELL // on \\ ELL
371
+ DIA// CPU \\DIA
372
+
373
+ Args:
374
+ source: source tensor
375
+ target: target tensor (partially constructed)
376
+ """
377
+
378
+ def __init__(self, source, target):
379
+ dim = source.num_dimensions
380
+ nse = source.nse
381
+ # Set fields.
382
+ self._source = source
383
+ self._target = target
384
+ self._indices = np.empty((dim, nse), dtype=target.index_type)
385
+ container_tp = np_enveloping_type(source.dtype)
386
+ self._values = np.empty((nse,), dtype=container_tp)
387
+ self._pos = 0
388
+
389
+ def run(self, stream=None):
390
+ # Intermediate COO is sorted if source format is sorted
391
+ # and uses an identity mapping. This may skip sorted
392
+ # if the target format has the same properties.
393
+ sformat = self._source.tensor_format
394
+ is_sorted = sformat.is_ordered and sformat.is_identity
395
+
396
+ # Run the decomposer and composer.
397
+ TensorDecomposer(self._source, self._visit).run(stream=stream)
398
+ pos, crd, val = TensorComposer(
399
+ self._source,
400
+ self._target,
401
+ self._indices[:, : self._pos],
402
+ self._values[: self._pos],
403
+ is_sorted,
404
+ ).run(stream=stream)
405
+
406
+ # Set directly (converter knows about UST conventions).
407
+ for idx in range(self._target.num_levels):
408
+ p = pos.get(idx)
409
+ if p is not None:
410
+ self._target._pos[idx] = wrap_operand(p)
411
+ c = crd.get(idx)
412
+ if c is not None:
413
+ self._target._crd[idx] = wrap_operand(c)
414
+ self._target._val = wrap_operand(val)
415
+
416
+ def _visit(self, dims, val):
417
+ if val == 0:
418
+ return # drop zeros (e.g. from dense or padding)
419
+ pos = self._pos
420
+ self._pos += 1
421
+ self._indices[:, pos] = dims[:]
422
+ self._values[pos] = val
@@ -0,0 +1,28 @@
1
+ # Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ """
6
+ This module defines C++ source code used by the UST.
7
+ """
8
+
9
+ __all__ = []
10
+
11
+ prolog_decl = """
12
+ extern "C" __device__ CTP prolog_a(CTP);
13
+ extern "C" __device__ CTP prolog_b(CTP);
14
+ """
15
+
16
+ prolog_a_impl = """
17
+ extern "C" __device__
18
+ CTP prolog_a(CTP a) {
19
+ return a;
20
+ }
21
+ """
22
+
23
+ prolog_b_impl = """
24
+ extern "C" __device__
25
+ CTP prolog_b(CTP b) {
26
+ return b;
27
+ }
28
+ """