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,565 @@
1
+ # Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ """
6
+ This module defines drawing methods for the universal sparse tensor (UST).
7
+ """
8
+
9
+ __all__ = []
10
+
11
+ import math
12
+
13
+ import numpy as np
14
+
15
+ from ._converters import TensorDecomposer
16
+ from ._utils import resolve_stream
17
+
18
+
19
+ class RequiredPackageError(Exception):
20
+ pass
21
+
22
+
23
+ WHITE = (0xFF, 0xFF, 0xFF)
24
+ BLACK = (0x00, 0x00, 0x00)
25
+ GRAY = (0xF0, 0xF0, 0xF0)
26
+ RED = (0xFF, 0x80, 0x80)
27
+ GREEN = (0x80, 0xFF, 0x80)
28
+ BLUE = (0x80, 0x80, 0xFF)
29
+ YELLOW = (0xFF, 0xFF, 0x80)
30
+ PURPLE = (0xFF, 0x08, 0xFF)
31
+
32
+
33
+ def _pos_length(tensor, i):
34
+ pos = tensor._pos.get(i)
35
+ if pos is not None:
36
+ return pos.size
37
+ return 0
38
+
39
+
40
+ def _crd_length(tensor, i):
41
+ crd = tensor._crd.get(i)
42
+ if crd is not None:
43
+ return crd.size
44
+ return 0
45
+
46
+
47
+ def _max_length(tensor):
48
+ length = tensor.nse
49
+ for i in range(tensor.num_levels):
50
+ length = max(length, _pos_length(tensor, i))
51
+ length = max(length, _crd_length(tensor, i))
52
+ return length
53
+
54
+
55
+ def _scale_font(txt, w):
56
+ try:
57
+ from PIL import ImageFont # type: ignore[import-not-found]
58
+ except ImportError as e:
59
+ raise RequiredPackageError("The PIL package is required for visualizing UST.") from e
60
+
61
+ length = len(txt)
62
+ f = max(8, w - length - 1)
63
+ off = 2 + max(0, 4 - length) * w // 4
64
+ try:
65
+ font = ImageFont.truetype("UbuntuMono-B.ttf", f)
66
+ except:
67
+ font = ImageFont.load_default(size=f)
68
+ return off, font
69
+
70
+
71
+ def draw_tensor(tensor, name=None, stream=None):
72
+ """
73
+ Draws tensor contents (1D, 2D, 3D).
74
+
75
+ This method is useful to illustrate tensor contents of smaller examples.
76
+
77
+ Args:
78
+ tensor: tensor to draw
79
+ name: filename to save to if not None
80
+ stream: the stream used to order any access to GPU-resident data
81
+ Returns:
82
+ Image, can be displayed with show()
83
+ """
84
+
85
+ try:
86
+ from PIL import Image, ImageDraw, ImageFont # type: ignore[import-not-found]
87
+ except ImportError as e:
88
+ raise RequiredPackageError("The PIL package is required for visualizing UST.") from e
89
+
90
+ if tensor.num_dimensions == 1:
91
+ M = 1
92
+ N = tensor.extents[0] # as row vector
93
+ K = 1
94
+ L1 = None
95
+ L2 = "i"
96
+ L3 = None
97
+ elif tensor.num_dimensions == 2:
98
+ M = tensor.extents[0]
99
+ N = tensor.extents[1]
100
+ K = 1
101
+ L1 = "i"
102
+ L2 = "j"
103
+ L3 = None
104
+ elif tensor.num_dimensions == 3:
105
+ M = tensor.extents[1]
106
+ N = tensor.extents[2]
107
+ K = tensor.extents[0] # i is batch, drawn horizontally
108
+ L1 = "j"
109
+ L2 = "k"
110
+ L3 = "i"
111
+ else:
112
+ raise TypeError(f"Cannot draw {tensor.num_dimensions}-dimensional tensor")
113
+
114
+ B = 8 # border
115
+ W = 32 # width unit
116
+ S = W // 4 # shadow unit
117
+ F = W // 2 # font unit
118
+ X = W + 2 * B + (S + S + N * W) * K - S
119
+ Y = W + 2 * B + S + M * W
120
+
121
+ try:
122
+ font = ImageFont.truetype("UbuntuMono-B.ttf", F)
123
+ except:
124
+ font = ImageFont.load_default(size=F)
125
+
126
+ img = Image.new("RGB", (X, Y), color=WHITE)
127
+ draw = ImageDraw.Draw(img)
128
+
129
+ def drawGrid(k):
130
+ xo = k * (N * W + S + S)
131
+ xs = B + W + xo
132
+ ys = B + W
133
+ xe = xs + N * W
134
+ ye = ys + M * W
135
+ draw.rectangle([xs + S, ys + S, xe + S, ye + S], fill=BLACK, outline=BLACK, width=1)
136
+ draw.rectangle([xs, ys, xe, ye], fill=WHITE, outline=BLACK, width=1)
137
+ x = xs
138
+ for _ in range(1, N):
139
+ x = x + W
140
+ draw.line([x, ys, x, ye], fill=BLACK, width=1)
141
+ y = ys
142
+ for _ in range(1, M):
143
+ y = y + W
144
+ draw.line([xs, y, xe, y], fill=BLACK, width=1)
145
+
146
+ def drawGridCell(i, j, k, txt, color=GRAY):
147
+ xo = k * (N * W + S + S)
148
+ xs = B + W + j * W + xo
149
+ ys = B + W + i * W
150
+ xe = xs + W
151
+ ye = ys + W
152
+ if False: # conditional cell coloring goes here
153
+ color = RED
154
+ draw.rectangle([xs, ys, xe, ye], fill=color, outline=BLACK, width=1)
155
+ off, vfont = _scale_font(txt, F)
156
+ draw.text([xs + off, ys + S], txt, fill=BLACK, font=vfont)
157
+
158
+ def visit123d(idx, val):
159
+ if len(idx) == 1:
160
+ drawGridCell(0, idx[0], 0, str(val))
161
+ elif len(idx) == 2:
162
+ drawGridCell(idx[0], idx[1], 0, str(val))
163
+ else:
164
+ drawGridCell(idx[1], idx[2], idx[0], str(val))
165
+
166
+ # Draw coordinate system.
167
+ draw.line([B, B, B + W, B + W], fill=BLACK, width=3)
168
+ if L1 is not None:
169
+ draw.text([B, B + F], L1, fill=BLACK, font=font)
170
+ for i in range(M):
171
+ draw.text([B + S, F + (i + 1) * W], str(i), fill=BLACK, font=font)
172
+ if L2 is not None:
173
+ draw.text([B + F + S, B], L2, fill=BLACK, font=font)
174
+ for i in range(N):
175
+ draw.text([F + (i + 1) * W, B + S], str(i), fill=BLACK, font=font)
176
+ if L3 is not None:
177
+ for i in range(K):
178
+ draw.text([B + W + i * (N * W + S + S), 0], f"{L3}={i}", fill=BLACK, font=font)
179
+
180
+ for k in range(K):
181
+ drawGrid(k)
182
+
183
+ TensorDecomposer(tensor, visit123d).run(stream=stream)
184
+
185
+ if name is not None:
186
+ img.save(name)
187
+ return img
188
+
189
+
190
+ def draw_tensor_storage(tensor, name=None, stream=None):
191
+ """
192
+ Draws tensor storage (UST).
193
+
194
+ This method is useful to illustrate the UST storage of smaller examples.
195
+
196
+ Args:
197
+ tensor: tensor to draw
198
+ name: filename to save to if not None
199
+ stream: the stream used to order any access to GPU-resident data
200
+ Returns:
201
+ Image, can be displayed with show()
202
+ """
203
+
204
+ try:
205
+ from PIL import Image, ImageDraw, ImageFont # type: ignore[import-not-found]
206
+ except ImportError as e:
207
+ raise RequiredPackageError("The PIL package is required for visualizing UST.") from e
208
+
209
+ # This method indexes single elements of the pos/crd/val arrays, so for
210
+ # GPU-resident data we copy to the host first (ordered on the provided stream).
211
+ if tensor.device_id != "cpu":
212
+ stream_holder = resolve_stream(stream, tensor)
213
+ tensor = tensor._to("cpu", stream_holder)
214
+
215
+ M = tensor.num_levels * 2 + 1
216
+ N = _max_length(tensor)
217
+ B = 8 # border
218
+ W = 32 # width unit
219
+ S = W // 4 # shadow unit
220
+ F = W // 2 # font unit
221
+ X = 2 * B + N * W + S + 2 * W
222
+ Y = 2 * B + M * (W + S + S) - S
223
+
224
+ try:
225
+ font = ImageFont.truetype("UbuntuMono-B.ttf", F)
226
+ except:
227
+ font = ImageFont.load_default(size=F)
228
+
229
+ img = Image.new("RGB", (X, Y), color=WHITE)
230
+ draw = ImageDraw.Draw(img)
231
+
232
+ def drawRow(i, txt, length, color=WHITE):
233
+ xs = B
234
+ ys = B + i * (W + S + S)
235
+ draw.text([xs, ys + S], txt, fill=BLACK, font=font)
236
+ xs = xs + 2 * W
237
+ xe = xs + (S if length == 0 else length * W)
238
+ ye = ys + W
239
+ draw.rectangle([xs + S, ys + S, xe + S, ye + S], fill=BLACK, outline=BLACK, width=1)
240
+ draw.rectangle([xs, ys, xe, ye], fill=color, outline=BLACK, width=1)
241
+ for _ in range(1, length):
242
+ xs = xs + W
243
+ draw.line([xs, ys, xs, ye], fill=BLACK, width=1)
244
+
245
+ def drawRowCell(i, j, txt, color=BLACK):
246
+ xs = B + 2 * W + j * W
247
+ ys = B + i * (W + S + S)
248
+ off, vfont = _scale_font(txt, F)
249
+ if False: # conditional cell coloring goes here
250
+ draw.rectangle([xs, ys, xs + W, ys + W], fill=RED, outline=BLACK, width=1)
251
+ draw.text([xs + off, ys + S], txt, fill=color, font=vfont)
252
+
253
+ for level in range(tensor.num_levels):
254
+ p = _pos_length(tensor, level)
255
+ drawRow(2 * level, f"pos[{level}]", p)
256
+ for j in range(p):
257
+ drawRowCell(2 * level, j, str(tensor._pos[level].tensor[j].item()))
258
+ c = _crd_length(tensor, level)
259
+ drawRow(2 * level + 1, f"crd[{level}]", c)
260
+ for j in range(c):
261
+ drawRowCell(2 * level + 1, j, str(tensor._crd[level].tensor[j].item()))
262
+ drawRow(M - 1, "values", tensor.nse)
263
+ for j in range(tensor.nse):
264
+ drawRowCell(M - 1, j, str(tensor._val.tensor[j].item()))
265
+
266
+ if name is not None:
267
+ img.save(name)
268
+ return img
269
+
270
+
271
+ def draw_tensor_raw(tensor, name=None, stream=None):
272
+ """
273
+ Draws tensor nonzero structure (2D, 3D).
274
+
275
+ This method scales to larger tensors.
276
+
277
+ Args:
278
+ tensor: tensor to draw
279
+ name: filename to save to if not None
280
+ stream: the stream used to order any access to GPU-resident data
281
+ Returns:
282
+ Image, can be displayed with show()
283
+ """
284
+ try:
285
+ from PIL import Image, ImageDraw, ImageFont # type: ignore[import-not-found]
286
+ except ImportError as e:
287
+ raise RequiredPackageError("The PIL package is required for visualizing UST.") from e
288
+
289
+ if tensor.num_dimensions == 2:
290
+ m, n, k = tensor.extents[1], tensor.extents[0], 0 # X goes down
291
+ elif tensor.num_dimensions == 3:
292
+ m, n, k = tensor.extents[0], tensor.extents[2], tensor.extents[1] # Z goes up
293
+ else:
294
+ raise TypeError(f"Cannot draw raw {tensor.num_dimensions}-dimensional tensor")
295
+
296
+ S = 0
297
+ while (m >> S) > 512:
298
+ S += 1
299
+ while (n >> S) > 512:
300
+ S += 1
301
+ while (k >> S) > 512:
302
+ S += 1
303
+ X = min(m, m >> S)
304
+ Y = min(n, n >> S)
305
+ Z = min(k, k >> S)
306
+ if ((m >> S) << S) != m:
307
+ X += 1
308
+ if ((n >> S) << S) != n:
309
+ Y += 1
310
+ if ((k >> S) << S) != k:
311
+ Z += 1
312
+ F = 16
313
+
314
+ try:
315
+ font = ImageFont.truetype("UbuntuMono-B.ttf", F)
316
+ except:
317
+ font = ImageFont.load_default(size=F)
318
+
319
+ img = Image.new("RGB", (X, Y), color=WHITE)
320
+ draw = ImageDraw.Draw(img)
321
+
322
+ if tensor.num_dimensions == 2:
323
+
324
+ def visit2d(idx, val):
325
+ img.putpixel((idx[1] >> S, idx[0] >> S), BLACK)
326
+
327
+ draw.line([0, 0, X - 1, 0], fill=RED, width=1)
328
+ draw.line([0, 0, 0, Y - 1], fill=RED, width=1)
329
+ draw.line([X - 1, 0, X - 1, Y - 1], fill=RED, width=1)
330
+ draw.line([0, Y - 1, X - 1, Y - 1], fill=RED, width=1)
331
+
332
+ TensorDecomposer(tensor, visit2d).run(stream=stream)
333
+
334
+ draw.text([0, Y / 2], "I", fill=BLUE, font=font, stroke_width=1.2)
335
+ draw.text([X / 2, 0], "J", fill=BLUE, font=font, stroke_width=1.2)
336
+ else:
337
+ # Fixed rotation around center in X/Z plane.
338
+ XR = 0
339
+ ZR = Z
340
+
341
+ # Fixed eye for projection.
342
+ D = Z * 2
343
+
344
+ # Rotation and translation (variable).
345
+ PHI = 45
346
+ XO = X // 2
347
+ YO = Y // 2
348
+ ZO = Z // 2
349
+
350
+ def project(x, y, z):
351
+ # Translate into view.
352
+ x = x - XO
353
+ y = y - YO
354
+ z = z + ZO
355
+ # Rotate [x,z,1].
356
+ co = math.cos(PHI)
357
+ si = math.sin(PHI)
358
+ xr = co * x - si * z + ((1 - co) * XR + si * ZR)
359
+ zr = si * x + co * z + ((1 - co) * ZR - si * XR)
360
+ x = xr
361
+ y = y
362
+ z = zr
363
+ # Project (if not in plane).
364
+ if z == -D:
365
+ x = x
366
+ y = y
367
+ else:
368
+ x = x * (D / (z + D))
369
+ y = y * (D / (z + D))
370
+ # Translate back.
371
+ x = int(x + XO)
372
+ y = int(y + YO)
373
+ return x, y, 0
374
+
375
+ def line(x1, y1, z1, x2, y2, z2):
376
+ (xp1, yp1, zp) = project(x1, y1, z1)
377
+ (xp2, yp2, zp) = project(x2, y2, z2)
378
+ draw.line([xp1, Y - yp1, xp2, Y - yp2], fill=RED, width=3)
379
+
380
+ def visit3d(idx, val):
381
+ x, y, z = project(idx[0] >> S, idx[2] >> S, idx[1] >> S)
382
+ # Guarded put pixel.
383
+ if x >= 0 and x < X and y >= 0 and y < Y:
384
+ img.putpixel((x, Y - y - 1), BLACK)
385
+
386
+ line(0, 0, 0, X, 0, 0)
387
+ line(0, 0, 0, 0, 0, Z)
388
+ line(X, 0, 0, X, 0, Z)
389
+ line(0, 0, Z, X, 0, Z)
390
+ line(0, Y, 0, X, Y, 0)
391
+ line(0, Y, 0, 0, Y, Z)
392
+ line(X, Y, 0, X, Y, Z)
393
+ line(0, Y, Z, X, Y, Z)
394
+ line(0, 0, 0, 0, Y, 0)
395
+ line(X, 0, 0, X, Y, 0)
396
+ line(0, 0, Z, 0, Y, Z)
397
+ line(X, 0, Z, X, Y, Z)
398
+
399
+ TensorDecomposer(tensor, visit3d).run(stream=stream)
400
+
401
+ (x, y, z) = project(X / 2, 0, 0)
402
+ draw.text([x, Y - y - 1], "I", fill=BLUE, font=font, stroke_width=1.2)
403
+ (x, y, z) = project(0, 0, Z / 2)
404
+ draw.text([x, Y - y - 1], "J", fill=BLUE, font=font, stroke_width=1.2)
405
+ (x, y, z) = project(0, Y / 2, 0)
406
+ draw.text([x, Y - y - 1], "K", fill=BLUE, font=font, stroke_width=1.2)
407
+
408
+ if name is not None:
409
+ img.save(name)
410
+ return img
411
+
412
+
413
+ def animate_tensor(tensor, name=None, stream=None):
414
+ """
415
+ Animates tensor nonzero structure (3D).
416
+
417
+ This method scales to larger tensors.
418
+
419
+ Args:
420
+ tensor: tensor to animate
421
+ name: filename to save to if not None
422
+ stream: the stream used to order any access to GPU-resident data
423
+ Returns:
424
+ HTML if name is None (to embed in other output)
425
+ """
426
+ try:
427
+ import matplotlib.pyplot as plt # type: ignore
428
+ from IPython.display import HTML # type: ignore
429
+ from matplotlib.animation import FuncAnimation, PillowWriter # type: ignore
430
+ except ImportError as e:
431
+ raise RequiredPackageError("Animation packages are required for visualizing UST.") from e
432
+
433
+ if tensor.num_dimensions == 3:
434
+ X, Y, Z = tensor.extents[0], tensor.extents[1], tensor.extents[2]
435
+ else:
436
+ raise TypeError(f"Cannot animate {tensor.num_dimensions}-dimensional tensor")
437
+
438
+ # Map largest to [0,1].
439
+ U = float(max(X, Y, Z))
440
+ X = X / U
441
+ Y = Y / U
442
+ Z = Z / U
443
+
444
+ points = np.empty((tensor.nse, 3), dtype=np.float32)
445
+ index = 0
446
+
447
+ def visit3d(idx, val):
448
+ nonlocal index
449
+ x, y, z = idx[0], idx[1], idx[2]
450
+ points[index, 0] = x / U
451
+ points[index, 1] = y / U
452
+ points[index, 2] = z / U
453
+ index += 1
454
+
455
+ TensorDecomposer(tensor, visit3d).run(stream=stream)
456
+
457
+ # Set up frame.
458
+ cube_vertices = np.array([[0, 0, 0], [X, 0, 0], [X, Y, 0], [0, Y, 0], [0, 0, Z], [X, 0, Z], [X, Y, Z], [0, Y, Z]])
459
+ cube_edges = np.array([[0, 1], [1, 2], [2, 3], [3, 0], [4, 5], [5, 6], [6, 7], [7, 4], [0, 4], [1, 5], [2, 6], [3, 7]])
460
+ fig = plt.figure(figsize=(5, 5), dpi=72)
461
+ ax = fig.add_subplot(111, projection="3d")
462
+
463
+ def update(frame):
464
+ ax.cla()
465
+ ax.set_axis_off()
466
+ ax.set_xlim(0, 1)
467
+ ax.set_ylim(0, 1)
468
+ ax.set_zlim(0, 1)
469
+
470
+ # Set the animation view.
471
+ elev = 45
472
+ azim = frame * 2 # degrees per frame
473
+ ax.view_init(elev=elev, azim=azim)
474
+
475
+ # Draw cube edges in red.
476
+ for edge in cube_edges:
477
+ v = cube_vertices[edge]
478
+ ax.plot3D(v[:, 0], v[:, 1], v[:, 2], color="red", linewidth=3, alpha=1)
479
+
480
+ # Draw points.
481
+ ax.scatter(points[:, 0], points[:, 1], points[:, 2], c="black", s=0.15, alpha=0.4, depthshade=True)
482
+
483
+ # Add labels at each axis
484
+ ax.text(X / 2, 0, 0, "I", fontsize=12, fontweight="bold", color="blue")
485
+ ax.text(0, Y / 2, 0, "J", fontsize=12, fontweight="bold", color="blue")
486
+ ax.text(0, 0, Z / 2, "K", fontsize=12, fontweight="bold", color="blue")
487
+
488
+ fig.subplots_adjust(left=0, right=1, top=1, bottom=0)
489
+
490
+ anim = FuncAnimation(fig, update, frames=180, interval=50)
491
+ plt.close()
492
+
493
+ if name is not None:
494
+ anim.save(name, writer=PillowWriter(fps=20))
495
+ else:
496
+ return HTML(anim.to_html5_video())
497
+
498
+
499
+ def draw_network(tensors, name=None):
500
+ """
501
+ Draws network consisting of linear layer weight matrices.
502
+
503
+ Args:
504
+ tensor: list of tensors to draw
505
+ name: filename to save to if not None
506
+ Returns:
507
+ Image, can be displayed with show()
508
+ """
509
+
510
+ try:
511
+ from PIL import Image, ImageDraw # type: ignore[import-not-found]
512
+ except ImportError as e:
513
+ raise RequiredPackageError("The PIL package is required for visualizing UST.") from e
514
+
515
+ CELLS = [tensor.shape[0] for tensor in tensors]
516
+ CELLS.append(tensors[-1].shape[1])
517
+ B = 8 # border
518
+ W = 32 # width unit
519
+ C1 = 4 # cell spacing start
520
+ C2 = W - C1 # cell spacing end
521
+ CO = W // 2
522
+ CL = len(CELLS)
523
+ CM = max(CELLS)
524
+ D = CM * W
525
+ X = 2 * B + D * (CL - 1) + W
526
+ Y = 2 * B + D
527
+
528
+ img = Image.new("RGB", (X, Y), color=WHITE)
529
+ draw = ImageDraw.Draw(img)
530
+
531
+ def drawCircle(i, cl, color=BLUE):
532
+ m = (CM - CELLS[cl]) / 2
533
+ x = B + cl * D
534
+ y = B + (i + m) * W
535
+ draw.ellipse((x + C1, y + C1, x + C2, y + C2), width=2, fill=color, outline=BLACK)
536
+
537
+ def drawLine(i, j, cl, color=BLACK):
538
+ m1 = (CM - CELLS[cl]) / 2
539
+ m2 = (CM - CELLS[cl + 1]) / 2
540
+ xs = B + cl * D + CO
541
+ ys = B + (i + m1) * W + CO
542
+ xe = xs + D
543
+ ye = B + (j + m2) * W + CO
544
+ draw.line([xs, ys, xe, ye], fill=color, width=1)
545
+
546
+ for cl in range(0, CL):
547
+ for i in range(0, CELLS[cl]):
548
+ drawCircle(i, cl)
549
+
550
+ for cl in range(0, CL - 1):
551
+
552
+ def visit(tensor, transposed, lvl):
553
+ def visit2d(idx, val):
554
+ if transposed:
555
+ drawLine(idx[1], idx[0], lvl)
556
+ else:
557
+ drawLine(idx[0], idx[1], lvl)
558
+
559
+ TensorDecomposer(tensor, visit2d).run()
560
+
561
+ visit(tensors[cl].ust, tensors[cl].transposed, cl)
562
+
563
+ if name is not None:
564
+ img.save(name)
565
+ return img