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,463 @@
1
+ # Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ import _numpy
6
+ from _typeshed import Incomplete
7
+ from typing import Any, ClassVar
8
+
9
+ __test__: dict
10
+
11
+ class NDBuffer:
12
+ """NDBuffer(*args, **kwargs)
13
+
14
+ NDBuffer is an n-dimensional view over a memory allocation.
15
+
16
+ .. warning::
17
+ This API is experimental and may change at any time.
18
+
19
+ Stream-semantics
20
+ In contrast to cupy, torch etc., there is no current stream notion at the NDBuffer level.
21
+ For this reason, calls that operate on device memory require passing
22
+ the stream explicitly.
23
+
24
+ .. _Custom memory resources:
25
+
26
+ Custom memory resources
27
+ Any custom memory resource provided by the user (see for example :meth:`~NDBuffer.empty` or
28
+ :meth:`~NDBuffer.copy_`), should adhere to the cuda.core.MemoryResource protocol.
29
+
30
+ When allocating new tensors (:meth:`~NDBuffer.empty`, :meth:`~NDBuffer.empty_like`),
31
+ NDBuffer simply forwards the user-provided ``stream``
32
+ argument to the memory resource's ``mr.allocate(size, stream)`` method and returns
33
+ the new allocation to the caller via :attr:`NDBuffer.data`.
34
+
35
+ In all cases, NDBuffer assumes that (currently or for the sake of future compatibility):
36
+
37
+ * Allocations with non-None stream ``mr.allocate(size, stream)`` are scheduled
38
+ on the provided stream and, by default, deallocation is scheduled on the same stream
39
+ (if not overridden with ``allocation.close(other_stream)``)
40
+ * Allocations with None stream ``mr.allocate(size, None)`` are host-synchronous
41
+ (safe to immediately access with host-blocking operations).
42
+ * Device memory resources are always stream-oriented (schedule allocation
43
+ and deallocation on the provided stream).
44
+ * Host memory resources can be either stream-oriented or host-synchronous.
45
+
46
+ Host-synchronous memory resource:
47
+ For example, regular malloc/free, or numpy.empty. The memory can be safely
48
+ accessed with host-blocking operations. If the memory is accessible
49
+ from a device, it can be safely accessed as long as the device
50
+ operations are synchronized with the host.
51
+
52
+ Stream-oriented memory resource:
53
+ Stream-oriented memory resource must ensure that operations
54
+ scheduled on the ``stream`` after allocation but before
55
+ deallocation call, can safely access the memory,
56
+ even if they execute asynchronously (i.e. they
57
+ may actually continue executing after the deallocation call).
58
+
59
+ For example:
60
+
61
+ * cuda asynchronous memory pool that schedules allocation on the provided ``stream``,
62
+ and uses the same ``stream`` to schedule deallocation.
63
+ * memory resources that enforce synchronization with the ``stream``
64
+ or the respective device after each allocation and deallocation.
65
+
66
+ In calls that may need to allocate workspace using the custom resources
67
+ (e.g. :meth:`~NDBuffer.copy_`), NDBuffer puts additional requirements
68
+ on the memory resources:
69
+
70
+ * Host memory resource must be able to act both as stream-oriented
71
+ (if it receives a stream) and host-synchronous (if it receives None).
72
+ * The memory resources must be able to accept different
73
+ streams for allocation and deallocation:
74
+
75
+ - The stream passed to ``mr.allocate(size, stream)``
76
+ may be different from the one passed by the user to NDBuffer call, and
77
+ - It must be possible to override the default stream order
78
+ for deallocation via ``allocation.close(stream)``.
79
+
80
+ Attributes
81
+ ----------
82
+ base : NDBuffer | None
83
+ The base NDBuffer. If not None, the current NDBuffer is a view created from
84
+ the base NDBuffer.
85
+ data : object
86
+ The data/allocation/buffer to view.
87
+ data_ptr : intptr_t
88
+ The raw pointer to memory held by ``data``. It points to the address
89
+ of element at index ``(0, ) * ndim``.
90
+
91
+ .. warning::
92
+ This pointer may not point to the beginning of the ``data`` buffer.
93
+ Even when limited to the layout's memory range, the pointer may not point
94
+ to the beginning of that range if the layout has negative strides.
95
+ dtype_name : str
96
+ The name of the dtype. The layout's itemsize must match the dtype's itemsize.
97
+ layout : StridedLayout
98
+ The layout of the NDBuffer."""
99
+ empty: ClassVar[method] = ...
100
+ empty_like: ClassVar[method] = ...
101
+ from_cupy: ClassVar[method] = ...
102
+ from_data: ClassVar[method] = ...
103
+ from_numpy: ClassVar[method] = ...
104
+ __pyx_vtable__: ClassVar[PyCapsule] = ...
105
+ base: Incomplete
106
+ data: Incomplete
107
+ data_ptr: Incomplete
108
+ device: Incomplete
109
+ device_id: Incomplete
110
+ dtype: NDBuffer.dtype
111
+ dtype_name: Incomplete
112
+ itemsize: Incomplete
113
+ layout: Incomplete
114
+ ndim: Incomplete
115
+ numpy_dtype: NDBuffer.numpy_dtype
116
+ raw_memory_range_info: Incomplete
117
+ shape: Incomplete
118
+ size: Incomplete
119
+ strides: Incomplete
120
+ strides_in_bytes: Incomplete
121
+ def __init__(self, *args, **kwargs) -> Any:
122
+ """
123
+ Don't instantiate NDBuffer directly. Use the following class methods instead:
124
+
125
+ * To create a view over existing data, use :meth:`~NDBuffer.from_data`, :meth:`~NDBuffer.from_numpy` or :meth:`~NDBuffer.from_cupy` instead.
126
+ * To allocate new memory, use :meth:`~NDBuffer.empty`, :meth:`~NDBuffer.empty_like`.
127
+ """
128
+ def as_numpy(self) -> Any:
129
+ """NDBuffer.as_numpy(self)
130
+
131
+ Returns a numpy array view of the NDBuffer's data, with the same
132
+ shape, strides, and dtype as the NDBuffer."""
133
+ def as_strided(self, StridedLayoutlayout=..., dtype: str | _numpy.dtype | None = ..., intoffset_in_bytes: int = ..., boolcheck_bounds: bool = ...) -> NDBuffer:
134
+ '''NDBuffer.as_strided(self, StridedLayout layout=None, dtype: str | _numpy.dtype | None = None, int offset_in_bytes: int = 0, bool check_bounds: bool = True) -> NDBuffer
135
+
136
+ Returns a NDBuffer that views the same memory/data, but with a new layout
137
+ and dtype, similar to `numpy.lib.stride_tricks.as_strided`, or `torch.as_strided`.
138
+
139
+ If specified, ``offset_in_bytes`` is the number of bytes to offset the current data pointer by.
140
+
141
+ If the ``check_bounds`` flag is set to True, the method will compare memory range
142
+ of the new layout with the memory range of the current instance\'s base
143
+ and raise a ValueError if the new range is not entirely contained within the old range.
144
+
145
+ .. highlight:: python
146
+ .. code-block:: python
147
+
148
+ a = np.arange(5*8, dtype=np.float32)
149
+ ndbuf = NDBuffer.from_numpy(a).reshape((5, 8))
150
+ view = ndbuf.view(np.complex64)[..., -1:1:-1]
151
+ np.testing.assert_array_equal(view.as_numpy(), a.reshape((5, 8)).view(np.complex64)[..., -1:1:-1])
152
+
153
+ # Now, if we get the repacked sliced layout and want to set it manually:
154
+ sliced_layout = StridedLayout.dense((5, 8), itemsize=4).packed(itemsize=8)[..., -1:1:-1]
155
+ view2 = ndbuf.as_strided(layout=sliced_layout.layout, dtype=np.complex64, offset_in_bytes=sliced_layout.slice_offset_in_bytes)
156
+ assert view.data_ptr == view2.data_ptr
157
+ assert view.layout == view2.layout
158
+
159
+
160
+ .. highlight:: python
161
+ .. code-block:: python
162
+
163
+ a = np.arange(7, dtype=np.float32)
164
+ narrow_view = NDBuffer.from_numpy(a)[3:4]
165
+ # We can get back a wider view over the same data
166
+ wider_view = narrow_view.as_strided(StridedLayout.dense(6, itemsize=4), offset_in_bytes=-8)
167
+ assert narrow_view.base[1:].data_ptr == wider_view.data_ptr
168
+ assert narrow_view.base[1:].layout == wider_view.layout
169
+
170
+ # This won\'t work with check_bounds true because NDBuffer doesn\'t know about
171
+ # the base "wide" view.
172
+ a = np.arange(7, dtype=np.float32)
173
+ narrow_view = NDBuffer.from_numpy(a[3:4])
174
+ try:
175
+ wider_view = narrow_view.as_strided(StridedLayout.dense(6, itemsize=4), offset_in_bytes=-8)
176
+ except ValueError as e:
177
+ assert "layout is incompatible" in str(e)
178
+ else:
179
+ assert False, "Expected ValueError"
180
+ wider_view = narrow_view.as_strided(StridedLayout.dense(6, itemsize=4), offset_in_bytes=-8, check_bounds=False)
181
+ assert NDBuffer.from_numpy(a[1:]).data_ptr == wider_view.data_ptr
182
+ assert NDBuffer.from_numpy(a[1:]).layout == wider_view.layout'''
183
+ def broadcast_to(self, layout: tuple[int] | int | StridedLayout) -> NDBuffer:
184
+ """NDBuffer.broadcast_to(self, layout: tuple[int] | int | StridedLayout) -> NDBuffer
185
+
186
+ Returns an NDBuffer that is a view of the same data, but with a layout broadcast
187
+ to match the provided shape.
188
+
189
+ The shapes are compatible if:
190
+
191
+ * the new shape has the same or greater number of dimensions,
192
+ * starting from the right, each extent in the old shape is 1 or equal to the
193
+ corresponding extent in the new shape.
194
+
195
+ Strides of the added or modified extents are set to 0; the remaining ones are
196
+ unchanged. Raises ``ValueError`` if the shapes are not compatible.
197
+
198
+ Parameters
199
+ ----------
200
+ layout : tuple[int] | int | StridedLayout
201
+ The new shape to broadcast to. If a :class:`StridedLayout` is passed, its
202
+ shape is used.
203
+
204
+
205
+ See also: :meth:`StridedLayout.broadcast_to`."""
206
+ def copy_(self, NDBuffersrc, stream=..., host_memory_resource=..., device_memory_resource=..., logger=..., boolblocking: bool | None = ...) -> Any:
207
+ """NDBuffer.copy_(self, NDBuffer src, *, stream=None, host_memory_resource=None, device_memory_resource=None, logger=None, bool blocking: bool | None = None)
208
+
209
+ Copies the data from the src NDBuffer to the current NDBuffer.
210
+
211
+ The src's shape must be equal or broadcastable to the current NDBuffer's shape.
212
+ The itemsize and dtype must be exactly the same.
213
+
214
+ By default, the D2D copies are non-blocking and D2H/H2D copies are blocking.
215
+ This can be overridden with the ``blocking`` argument.
216
+ H2H copies are always blocking and the ``blocking`` argument is ignored.
217
+
218
+ .. note::
219
+ Extra requirements apply to the provided memory resources
220
+ (see :ref:`Custom memory resources` for details).
221
+
222
+ .. note::
223
+ In complex cases that require extra temporary copies, NDBuffer may ignore the
224
+ non-blocking flag and decide to explicitly synchronize the stream.
225
+
226
+ .. note::
227
+ For H2D async copies, NDBuffer explicitly copies the src memory to
228
+ temporary host buffer in order to ensure that the src memory is safe to
229
+ write to immediately after the `copy_` call returns."""
230
+ def fill_(self, value, stream=..., logger=..., boolblocking: bool | None = ...) -> Any:
231
+ """NDBuffer.fill_(self, value, *, stream=None, logger=None, bool blocking: bool | None = None)
232
+
233
+ Fills the current NDBuffer with the given value (scalar, list, numpy array, etc.).
234
+
235
+ The ``value`` must be convertible to a numpy array of the same dtype as the current
236
+ NDBuffer's dtype, and broadcastable to the current NDBuffer's shape.
237
+
238
+ .. note::
239
+ The NDBuffer's dtype must be supported by numpy in order to use this method.
240
+ For unsupported dtypes, use the :meth:`~NDBuffer.copy_` method instead."""
241
+ def item(self, stream=...) -> Any:
242
+ """NDBuffer.item(self, *, stream=None)
243
+
244
+ For a tensor of volume 1, returns the scalar value as Python object.
245
+ If the tensor is in device memory, a stream must be provided - there
246
+ will be a blocking copy to the host scheduled on that stream.
247
+
248
+ .. note::
249
+ The NDBuffer's dtype must be supported by numpy in order to use this method."""
250
+ def permute(self, tuplepermutation: tuple[int], boolinverse: bool = ...) -> NDBuffer:
251
+ """NDBuffer.permute(self, tuple permutation: tuple[int], bool inverse: bool = False) -> NDBuffer
252
+
253
+ Returns an NDBuffer that is a view of the same data, but with the shape and
254
+ strides permuted according to ``permutation``.
255
+
256
+ Parameters
257
+ ----------
258
+ permutation : tuple[int]
259
+ The permutation of axes to apply.
260
+ inverse : bool
261
+ If True, the inverse permutation is applied (equivalently, permuting the
262
+ result by ``permutation`` yields the original layout). Defaults to False.
263
+
264
+
265
+ See also: :meth:`StridedLayout.permuted`."""
266
+ def repack(self, dtype: str | _numpy.dtype, intitemsize: int | None = ..., intaxis=...) -> NDBuffer:
267
+ """NDBuffer.repack(self, dtype: str | _numpy.dtype, int itemsize: int | None = None, int axis=-1) -> NDBuffer
268
+
269
+ Returns a NDBuffer that is a view of the same data, but with a new dtype and itemsize.
270
+ The shape and strides are adjusted accordingly.
271
+ Raises ValueError if the new dtype is not compatible with the current layout.
272
+
273
+ Parameters
274
+ ----------
275
+ dtype : str | numpy.dtype
276
+ The dtype of the returned view.
277
+ itemsize : int | None
278
+ A hint for the repacking case. If not provided, it is inferred from
279
+ ``dtype`` (via numpy). Omitting it raises an error if the dtype is not supported
280
+ by numpy.
281
+ axis : int
282
+ The axis along which elements are packed/unpacked. Defaults to the last axis.
283
+
284
+
285
+ See also: :meth:`StridedLayout.packed` and :meth:`StridedLayout.unpacked`."""
286
+ def reshape(self, shape: tuple[int] | int | StridedLayout) -> NDBuffer:
287
+ """NDBuffer.reshape(self, shape: tuple[int] | int | StridedLayout) -> NDBuffer
288
+
289
+ Returns a NDBuffer that is a view of the same data, but with a new shape.
290
+
291
+ .. note::
292
+ This method behaves similarly to numpy's ``reshape(..., copy=False)``, i.e.
293
+ it never allocates or copies the data, it only creates a new
294
+ view of the existing data. It will raise ValueError if the new shape
295
+ is not compatible with the current layout.
296
+
297
+ The new shape is compatible if:
298
+
299
+ * the new and old shapes have the same volume,
300
+ * the old strides can be split or flattened to match the new shape,
301
+ assuming indices are iterated in C-order.
302
+
303
+ A single extent in ``shape`` can be set to ``-1`` to indicate it should be
304
+ inferred from the old volume and the other extents.
305
+
306
+ Parameters
307
+ ----------
308
+ shape : tuple[int] | int | StridedLayout
309
+ The new shape. If a :class:`StridedLayout` is passed, its shape is used.
310
+
311
+
312
+ See also: :meth:`StridedLayout.reshaped`."""
313
+ def squeeze(self, axis: int | tuple[int] | None = ..., intmask: int | None = ...) -> NDBuffer:
314
+ """NDBuffer.squeeze(self, axis: int | tuple[int] | None = None, int mask: int | None = None) -> NDBuffer
315
+
316
+ Returns an NDBuffer that is a view of the same data, but with the selected unit
317
+ dimensions (extents equal to 1) removed.
318
+
319
+ To limit which axes are considered for squeezing, use one of the ``axis`` or
320
+ ``mask`` parameters. If neither is provided, all unit dimensions are removed.
321
+
322
+ Parameters
323
+ ----------
324
+ axis : int | tuple[int] | None
325
+ The axis or axes to consider for squeezing.
326
+ mask : int | None
327
+ Alternative to ``axis``: a bitmask selecting the axes to consider for squeezing.
328
+
329
+
330
+ See also: :meth:`StridedLayout.squeezed`."""
331
+ def transpose(self, intaxis_a: int, intaxis_b: int) -> NDBuffer:
332
+ """NDBuffer.transpose(self, int axis_a: int, int axis_b: int) -> NDBuffer
333
+
334
+ Returns an NDBuffer that is a view of the same data, but with the two specified
335
+ axes swapped.
336
+
337
+ Parameters
338
+ ----------
339
+ axis_a, axis_b : int
340
+ The two axes to swap.
341
+
342
+
343
+ See also: :meth:`StridedLayout.transposed`."""
344
+ def unsqueeze(self, axis: int | tuple[int] | None = ..., intmask: int = ...) -> NDBuffer:
345
+ """NDBuffer.unsqueeze(self, axis: int | tuple[int] | None = None, int mask: int = 0) -> NDBuffer
346
+
347
+ Returns an NDBuffer that is a view of the same data, but with unit extents
348
+ (extents equal to 1) added at the selected positions.
349
+
350
+ Parameters
351
+ ----------
352
+ axis : int | tuple[int] | None
353
+ The position(s) at which to insert the new unit extents. It can be either
354
+ a single integer in range ``[0, ndim]`` or a tuple of
355
+ unique integers in range ``[0, ndim + len(axis) - 1]``.
356
+ mask : int
357
+ Alternative to ``axis``: a bitmask selecting the positions
358
+ of the new unit extents.
359
+
360
+
361
+ See also: :meth:`StridedLayout.unsqueezed`."""
362
+ def view(self, shape_or_dtype, intitemsize: int | None = ...) -> NDBuffer:
363
+ """NDBuffer.view(self, shape_or_dtype, int itemsize: int | None = None) -> NDBuffer
364
+
365
+ Convenience method aiming to match the numpy.ndarray/torch.view methods,
366
+ it either reshapes or repacks the current NDBuffer to the new shape or dtype.
367
+
368
+ Parameters
369
+ ----------
370
+ shape_or_dtype : tuple[int] | int | str | numpy.dtype
371
+ The new shape or dtype. If a tuple, it is interpreted as a new shape and the
372
+ call is equivalent to :meth:`~NDBuffer.reshape`.
373
+ Otherwise, the argument must be a dtype name string or a numpy.dtype object
374
+ and the call is equivalent to :meth:`~NDBuffer.repack`.
375
+ itemsize : int | None
376
+ A hint for the repacking case. If not provided, it is inferred from
377
+ ``dtype`` (via numpy). Omitting it raises an error if the dtype is not supported
378
+ by numpy.
379
+
380
+
381
+ See also: :meth:`~NDBuffer.reshape` and :meth:`~NDBuffer.repack`."""
382
+ def __delitem__(self, other) -> None:
383
+ """Delete self[key]."""
384
+ def __eq__(self, other) -> Any:
385
+ """NDBuffer.__eq__(self, other)
386
+
387
+ The default (equality is identity) comparison can be misleading.
388
+ User may expect number of meanings here:
389
+ * identity comparison
390
+ * compare meta-data, allocation and layout
391
+ * diapatch elementwise comparison (and possibly reduce the result for vol > 1).
392
+
393
+ Until we decide if any of those meanings is useful and worth implementing,
394
+ we return NotImplementedError to force Python to raise an error
395
+ rather than fallback to identity or try ``__eq__`` method from ``other``
396
+
397
+ .. note::
398
+ As an example, take NDBuffer and ``ndbuffer[i] == 3`` expression.
399
+ Clearly, one can expect that the expression compares data stored
400
+ in the memory at index ``i``, while the default comparison would
401
+ silently always evaluate to False. For now, to compare single
402
+ element, one can use the :meth:`~NDBuffer.item` method
403
+ (i.e. ``ndbuffer.item() == 3``).
404
+
405
+ .. note::
406
+ As we override the ``__eq__`` method, the object is not hashable.
407
+ This is intentional and is unlikely to change even if we decide to implement
408
+ comparison. Hashing requires immutability, so if equality involves
409
+ comparing the values stored in the tensor, we cannot have hashing."""
410
+ def __ge__(self, other: object) -> bool:
411
+ """Return self>=value."""
412
+ def __getitem__(self, index):
413
+ """Return self[key]."""
414
+ def __gt__(self, other: object) -> bool:
415
+ """Return self>value."""
416
+ def __le__(self, other: object) -> bool:
417
+ """Return self<=value."""
418
+ def __len__(self) -> int:
419
+ """Return len(self)."""
420
+ def __lt__(self, other: object) -> bool:
421
+ """Return self<value."""
422
+ def __ne__(self, other: object) -> bool:
423
+ """Return self!=value."""
424
+ def __reduce__(self):
425
+ """NDBuffer.__reduce_cython__(self)"""
426
+ def __reduce_cython__(self) -> Any:
427
+ """NDBuffer.__reduce_cython__(self)"""
428
+ def __setitem__(self, slices: int | slice | tuple[int | slice], value) -> Any:
429
+ '''NDBuffer.__setitem__(self, slices: int | slice | tuple[int | slice], value)
430
+
431
+ Assigns the value to (possibly a slice of) the tensor.
432
+
433
+ .. warning::
434
+ Both the NDBuffer being assigned to and the assigned value
435
+ must reside on the host. Note, there\'s no "default stream" for
436
+ NDBuffers, so any device memory accesses require an explicit
437
+ cuda stream, which is not supported with the assignment syntax.
438
+ For those cases, please use the copy_ or fill_ methods.'''
439
+ def __setstate_cython__(self, __pyx_state) -> Any:
440
+ """NDBuffer.__setstate_cython__(self, __pyx_state)"""
441
+
442
+ class _NDBufferAsBufferProxy:
443
+ """
444
+ Proxy class that exposes the underlying host allocation as flat (1D) Python buffer.
445
+
446
+ .. note::
447
+ Defining the __getbuffer__ implicitly makes the created buffer object
448
+ reference the exporting object (the one that defines the __getbuffer__),
449
+ If the __getbuffer__ was defined on the NDBuffer itself, we'd end up
450
+ with a circular dependency:
451
+ NDBuffer -> NDBuffer.numpy_view -> buffer object -> NDBuffer
452
+ """
453
+ @classmethod
454
+ def __init__(cls, *args, **kwargs) -> None:
455
+ """Create and return a new object. See help(type) for accurate signature."""
456
+ def __buffer__(self, *args, **kwargs):
457
+ """Return a buffer object that exposes the underlying memory of the object."""
458
+ def __reduce__(self):
459
+ """_NDBufferAsBufferProxy.__reduce_cython__(self)"""
460
+ def __reduce_cython__(self) -> Any:
461
+ """_NDBufferAsBufferProxy.__reduce_cython__(self)"""
462
+ def __setstate_cython__(self, __pyx_state) -> Any:
463
+ """_NDBufferAsBufferProxy.__setstate_cython__(self, __pyx_state)"""
@@ -0,0 +1,34 @@
1
+ // Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+
5
+ #ifndef NVMATH_COPY_KERNEL_IMPL_ARGS_H
6
+ #define NVMATH_COPY_KERNEL_IMPL_ARGS_H
7
+
8
+ #include "copy_kernel_impl/type_utils.h"
9
+
10
+ #if defined(_MSC_VER)
11
+ // For Visual Studio, use __restrict
12
+ #define RESTRICT __restrict
13
+ #elif defined(__GNUC__) || defined(__clang__)
14
+ // For GCC and Clang, use __restrict__
15
+ #define RESTRICT __restrict__
16
+ #else
17
+ // Fallback for other compilers, or if restrict is not supported
18
+ #define RESTRICT
19
+ #endif
20
+
21
+ namespace nvmath {
22
+ template <int N>
23
+ struct KernelArgs {
24
+ void * RESTRICT dst_ptr;
25
+ const void * RESTRICT src_ptr;
26
+ int64_t dst_shape[N];
27
+ int64_t src_shape[N];
28
+ int64_t dst_strides[N];
29
+ int64_t src_strides[N];
30
+ int64_t grid_arg;
31
+ };
32
+ }
33
+
34
+ #endif // NVMATH_COPY_KERNEL_IMPL_ARGS_H
@@ -0,0 +1,52 @@
1
+ // Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+
5
+ #ifndef NVMATH_COPY_KERNEL_IMPL_ARRAY_VIEW_H_
6
+ #define NVMATH_COPY_KERNEL_IMPL_ARRAY_VIEW_H_
7
+
8
+ #include "copy_kernel_impl/utils.h"
9
+ #include "copy_kernel_impl/vec.h"
10
+
11
+ #if defined(_MSC_VER)
12
+ // For Visual Studio, use __restrict
13
+ #define RESTRICT __restrict
14
+ #elif defined(__GNUC__) || defined(__clang__)
15
+ // For GCC and Clang, use __restrict__
16
+ #define RESTRICT __restrict__
17
+ #else
18
+ // Fallback for other compilers, or if restrict is not supported
19
+ #define RESTRICT
20
+ #endif
21
+
22
+ namespace nvmath {
23
+
24
+ template <typename T, typename _coords_t> struct array_view {
25
+ // While indices cannot be negative (only strides can),
26
+ // we're using the same 32- or 64-bit signed type to represent both
27
+ // indices and strides for simplicity. In the end we need to convert
28
+ // both to the same signed type when computing the offset.
29
+ using coords_t = _coords_t;
30
+ using stride_t = typename coords_t::type;
31
+ using dtype_t = T;
32
+ static constexpr int ndim = coords_t::ndim;
33
+
34
+ HOST_DEV constexpr array_view(T *__restrict__ data, coords_t shape, coords_t strides)
35
+ : shape_(shape), strides_(strides), data_(data) {}
36
+
37
+ HOST_DEV __forceinline__ T &operator[](const coords_t idx) const { return data_[offset(idx)]; }
38
+ HOST_DEV __forceinline__ T &operator[](const stride_t offset) const { return data_[offset]; }
39
+ HOST_DEV __forceinline__ stride_t offset(const coords_t idx) const { return dot(idx, strides()); }
40
+ HOST_DEV __forceinline__ coords_t shape() const { return shape_; }
41
+ HOST_DEV __forceinline__ coords_t strides() const { return strides_; }
42
+ HOST_DEV __forceinline__ T *data() const { return data_; }
43
+
44
+ protected:
45
+ coords_t shape_;
46
+ coords_t strides_;
47
+ T *RESTRICT data_;
48
+ };
49
+
50
+ } // namespace nvmath
51
+
52
+ #endif // NVMATH_COPY_KERNEL_IMPL_ARRAY_VIEW_H_
@@ -0,0 +1,68 @@
1
+ // Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+
5
+ #ifndef NVMATH_COPY_KERNEL_IMPL_ELEMENTWISE_H
6
+ #define NVMATH_COPY_KERNEL_IMPL_ELEMENTWISE_H
7
+
8
+ #include "copy_kernel_impl/array_view.h"
9
+ #include "copy_kernel_impl/grid_indexer.h"
10
+ #include "copy_kernel_impl/type_utils.h"
11
+ #include "copy_kernel_impl/utils.h"
12
+ #include "copy_kernel_impl/vec.h"
13
+
14
+ namespace nvmath {
15
+
16
+ namespace detail {
17
+
18
+ template <typename coords_t, typename stride_t = typename coords_t::type>
19
+ __device__ __forceinline__ coords_t unravel_idx(const stride_t flat_idx, const coords_t shape) {
20
+ constexpr int ndim = coords_t::ndim;
21
+ if constexpr (ndim <= 0) {
22
+ return {};
23
+ } else if constexpr (ndim == 1) {
24
+ return {flat_idx};
25
+ } else if constexpr (ndim > 1) {
26
+
27
+ // the extents cannot be negative and the arithmetic on unsigned integer
28
+ // is noticeably faster
29
+ using u_stride_t = typename type_traits::unsign<stride_t>::type;
30
+ u_stride_t u_flat_idx = flat_idx;
31
+ coords_t unraveled_coords;
32
+ #pragma unroll
33
+ for (int i = ndim - 1; i >= 1; i--) {
34
+ u_stride_t extent = shape[i];
35
+ if (extent & (extent - 1)) {
36
+ u_stride_t next_flat_idx = u_flat_idx / extent;
37
+ unraveled_coords[i] = u_flat_idx - next_flat_idx * extent;
38
+ u_flat_idx = next_flat_idx;
39
+ } else {
40
+ unraveled_coords[i] = u_flat_idx & (extent - 1);
41
+ u_flat_idx >>= ffs(extent) - 1;
42
+ }
43
+ }
44
+ unraveled_coords[0] = u_flat_idx;
45
+ return unraveled_coords;
46
+ }
47
+ }
48
+
49
+ } // namespace detail
50
+
51
+ template <bool has_equal_shapes, typename dst_array_view_t, typename src_array_view_t, typename grid_indexer_t>
52
+ struct elementwise_copy_impl {
53
+ using stride_t = typename dst_array_view_t::stride_t;
54
+
55
+ void __forceinline__ __device__ operator()(const dst_array_view_t &&dst_view, const src_array_view_t &&src_view,
56
+ const grid_indexer_t &&grid_helper) {
57
+ grid_helper.with_grid_stride_loop([=](const stride_t flat_element_idx) {
58
+ const auto dst_coords = detail::unravel_idx(flat_element_idx, dst_view.shape());
59
+ const auto src_coords =
60
+ cond_val(bconst<has_equal_shapes>(), dst_coords, detail::unravel_idx(flat_element_idx, src_view.shape()));
61
+ dst_view[dst_coords] = src_view[src_coords];
62
+ });
63
+ }
64
+ };
65
+
66
+ } // namespace nvmath
67
+
68
+ #endif // NVMATH_COPY_KERNEL_IMPL_ELEMENTWISE_H