nvmath-python 0.9.0__cp314-cp314-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 (309) 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 +383 -0
  7. nvmath/_utils.py +150 -0
  8. nvmath/bindings/__init__.py +51 -0
  9. nvmath/bindings/_internal/__init__.pxd +0 -0
  10. nvmath/bindings/_internal/__init__.py +0 -0
  11. nvmath/bindings/_internal/cublas.cp314-win_amd64.pyd +0 -0
  12. nvmath/bindings/_internal/cublas.pxd +530 -0
  13. nvmath/bindings/_internal/cublasLt.cp314-win_amd64.pyd +0 -0
  14. nvmath/bindings/_internal/cublasLt.pxd +59 -0
  15. nvmath/bindings/_internal/cublasMp.pxd +52 -0
  16. nvmath/bindings/_internal/cudss.cp314-win_amd64.pyd +0 -0
  17. nvmath/bindings/_internal/cudss.pxd +47 -0
  18. nvmath/bindings/_internal/cufft.cp314-win_amd64.pyd +0 -0
  19. nvmath/bindings/_internal/cufft.pxd +70 -0
  20. nvmath/bindings/_internal/cufftMp.pxd +77 -0
  21. nvmath/bindings/_internal/curand.cp314-win_amd64.pyd +0 -0
  22. nvmath/bindings/_internal/curand.pxd +42 -0
  23. nvmath/bindings/_internal/cusolver.cp314-win_amd64.pyd +0 -0
  24. nvmath/bindings/_internal/cusolver.pxd +15 -0
  25. nvmath/bindings/_internal/cusolverDn.cp314-win_amd64.pyd +0 -0
  26. nvmath/bindings/_internal/cusolverDn.pxd +406 -0
  27. nvmath/bindings/_internal/cusparse.cp314-win_amd64.pyd +0 -0
  28. nvmath/bindings/_internal/cusparse.pxd +277 -0
  29. nvmath/bindings/_internal/cusparseLt.cp314-win_amd64.pyd +0 -0
  30. nvmath/bindings/_internal/cusparseLt.pxd +48 -0
  31. nvmath/bindings/_internal/cutensor.cp314-win_amd64.pyd +0 -0
  32. nvmath/bindings/_internal/cutensor.pxd +58 -0
  33. nvmath/bindings/_internal/mathdx.cp314-win_amd64.pyd +0 -0
  34. nvmath/bindings/_internal/mathdx.pxd +116 -0
  35. nvmath/bindings/_internal/nvshmem.pxd +29 -0
  36. nvmath/bindings/_internal/utils.cp314-win_amd64.pyd +0 -0
  37. nvmath/bindings/_internal/utils.pxd +179 -0
  38. nvmath/bindings/_internal/utils.pyi +10 -0
  39. nvmath/bindings/cublas.cp314-win_amd64.pyd +0 -0
  40. nvmath/bindings/cublas.pxd +558 -0
  41. nvmath/bindings/cublas.pyi +746 -0
  42. nvmath/bindings/cublasLt.cp314-win_amd64.pyd +0 -0
  43. nvmath/bindings/cublasLt.pxd +109 -0
  44. nvmath/bindings/cublasLt.pyi +1337 -0
  45. nvmath/bindings/cublasMp.pxd +85 -0
  46. nvmath/bindings/cublasMp.pyi +219 -0
  47. nvmath/bindings/cudss.cp314-win_amd64.pyd +0 -0
  48. nvmath/bindings/cudss.pxd +86 -0
  49. nvmath/bindings/cudss.pyi +282 -0
  50. nvmath/bindings/cufft.cp314-win_amd64.pyd +0 -0
  51. nvmath/bindings/cufft.pxd +118 -0
  52. nvmath/bindings/cufft.pyi +241 -0
  53. nvmath/bindings/cufftMp.pxd +124 -0
  54. nvmath/bindings/cufftMp.pyi +260 -0
  55. nvmath/bindings/curand.cp314-win_amd64.pyd +0 -0
  56. nvmath/bindings/curand.pxd +71 -0
  57. nvmath/bindings/curand.pyi +159 -0
  58. nvmath/bindings/cusolver.cp314-win_amd64.pyd +0 -0
  59. nvmath/bindings/cusolver.pxd +62 -0
  60. nvmath/bindings/cusolver.pyi +242 -0
  61. nvmath/bindings/cusolverDn.cp314-win_amd64.pyd +0 -0
  62. nvmath/bindings/cusolverDn.pxd +430 -0
  63. nvmath/bindings/cusolverDn.pyi +416 -0
  64. nvmath/bindings/cusparse.cp314-win_amd64.pyd +0 -0
  65. nvmath/bindings/cusparse.pxd +338 -0
  66. nvmath/bindings/cusparse.pyi +659 -0
  67. nvmath/bindings/cusparseLt.cp314-win_amd64.pyd +0 -0
  68. nvmath/bindings/cusparseLt.pxd +99 -0
  69. nvmath/bindings/cusparseLt.pyi +198 -0
  70. nvmath/bindings/cutensor.cp314-win_amd64.pyd +0 -0
  71. nvmath/bindings/cutensor.pxd +98 -0
  72. nvmath/bindings/cutensor.pyi +294 -0
  73. nvmath/bindings/cycublas.cp314-win_amd64.pyd +0 -0
  74. nvmath/bindings/cycublas.pxd +684 -0
  75. nvmath/bindings/cycublasLt.cp314-win_amd64.pyd +0 -0
  76. nvmath/bindings/cycublasLt.pxd +1055 -0
  77. nvmath/bindings/cycublasMp.pxd +183 -0
  78. nvmath/bindings/cycudss.cp314-win_amd64.pyd +0 -0
  79. nvmath/bindings/cycudss.pxd +224 -0
  80. nvmath/bindings/cycufft.cp314-win_amd64.pyd +0 -0
  81. nvmath/bindings/cycufft.pxd +326 -0
  82. nvmath/bindings/cycufftMp.pxd +334 -0
  83. nvmath/bindings/cycurand.cp314-win_amd64.pyd +0 -0
  84. nvmath/bindings/cycurand.pxd +146 -0
  85. nvmath/bindings/cycusolver.cp314-win_amd64.pyd +0 -0
  86. nvmath/bindings/cycusolver.pxd +154 -0
  87. nvmath/bindings/cycusolverDn.cp314-win_amd64.pyd +0 -0
  88. nvmath/bindings/cycusolverDn.pxd +446 -0
  89. nvmath/bindings/cycusparse.cp314-win_amd64.pyd +0 -0
  90. nvmath/bindings/cycusparse.pxd +470 -0
  91. nvmath/bindings/cycusparseLt.cp314-win_amd64.pyd +0 -0
  92. nvmath/bindings/cycusparseLt.pxd +150 -0
  93. nvmath/bindings/cycutensor.cp314-win_amd64.pyd +0 -0
  94. nvmath/bindings/cycutensor.pxd +192 -0
  95. nvmath/bindings/cymathdx.cp314-win_amd64.pyd +0 -0
  96. nvmath/bindings/cymathdx.pxd +552 -0
  97. nvmath/bindings/cynvshmem.pxd +126 -0
  98. nvmath/bindings/mathdx.cp314-win_amd64.pyd +0 -0
  99. nvmath/bindings/mathdx.pxd +182 -0
  100. nvmath/bindings/mathdx.pyi +1244 -0
  101. nvmath/bindings/nvpl/__init__.pxd +0 -0
  102. nvmath/bindings/nvpl/__init__.py +13 -0
  103. nvmath/bindings/nvpl/_internal/__init__.pxd +0 -0
  104. nvmath/bindings/nvpl/_internal/__init__.py +0 -0
  105. nvmath/bindings/nvpl/_internal/blas.cp314-win_amd64.pyd +0 -0
  106. nvmath/bindings/nvpl/_internal/blas.pxd +125 -0
  107. nvmath/bindings/nvpl/_internal/fft.cp314-win_amd64.pyd +0 -0
  108. nvmath/bindings/nvpl/_internal/fft.pxd +36 -0
  109. nvmath/bindings/nvpl/blas.cp314-win_amd64.pyd +0 -0
  110. nvmath/bindings/nvpl/blas.pxd +85 -0
  111. nvmath/bindings/nvpl/blas.pyi +122 -0
  112. nvmath/bindings/nvpl/cyblas.cp314-win_amd64.pyd +0 -0
  113. nvmath/bindings/nvpl/cyblas.pxd +166 -0
  114. nvmath/bindings/nvpl/cyfft.cp314-win_amd64.pyd +0 -0
  115. nvmath/bindings/nvpl/cyfft.pxd +92 -0
  116. nvmath/bindings/nvpl/fft.cp314-win_amd64.pyd +0 -0
  117. nvmath/bindings/nvpl/fft.pxd +100 -0
  118. nvmath/bindings/nvpl/fft.pyi +100 -0
  119. nvmath/bindings/nvshmem.pxd +54 -0
  120. nvmath/bindings/nvshmem.pyi +179 -0
  121. nvmath/device/__init__.py +21 -0
  122. nvmath/device/_deprecated.py +33 -0
  123. nvmath/device/common.py +313 -0
  124. nvmath/device/common_backend.py +131 -0
  125. nvmath/device/common_cuda.py +201 -0
  126. nvmath/device/common_numba.py +310 -0
  127. nvmath/device/common_opaque_tensor.py +201 -0
  128. nvmath/device/cublasdx.py +1805 -0
  129. nvmath/device/cublasdx_backend.py +807 -0
  130. nvmath/device/cublasdx_numba.py +1612 -0
  131. nvmath/device/cufftdx.py +510 -0
  132. nvmath/device/cufftdx_backend.py +196 -0
  133. nvmath/device/cufftdx_numba.py +196 -0
  134. nvmath/device/curand_kernel.py +9147 -0
  135. nvmath/device/cusolverdx.py +2690 -0
  136. nvmath/device/cusolverdx_backend.py +440 -0
  137. nvmath/device/cusolverdx_numba.py +1624 -0
  138. nvmath/device/llvm_array.py +29 -0
  139. nvmath/device/random.py +445 -0
  140. nvmath/device/random_helpers.py +23 -0
  141. nvmath/device/random_states.py +187 -0
  142. nvmath/device/types.py +147 -0
  143. nvmath/device/vector_types_numba.py +203 -0
  144. nvmath/distributed/__init__.py +205 -0
  145. nvmath/distributed/_internal/__init__.py +0 -0
  146. nvmath/distributed/_internal/nvshmem.py +302 -0
  147. nvmath/distributed/_internal/tensor_ifc.py +67 -0
  148. nvmath/distributed/_internal/tensor_ifc_cupy.py +62 -0
  149. nvmath/distributed/_internal/tensor_ifc_host_device.py +165 -0
  150. nvmath/distributed/_internal/tensor_ifc_numpy.py +41 -0
  151. nvmath/distributed/_internal/tensor_ifc_torch.py +141 -0
  152. nvmath/distributed/_internal/tensor_wrapper.py +78 -0
  153. nvmath/distributed/_utils.py +167 -0
  154. nvmath/distributed/distribution.py +770 -0
  155. nvmath/distributed/fft/__init__.py +7 -0
  156. nvmath/distributed/fft/_configuration.py +79 -0
  157. nvmath/distributed/fft/fft.py +2801 -0
  158. nvmath/distributed/linalg/__init__.py +12 -0
  159. nvmath/distributed/linalg/_internal/__init__.py +3 -0
  160. nvmath/distributed/linalg/_internal/epilog_protocol.py +496 -0
  161. nvmath/distributed/linalg/_internal/matmul_desc_ifc.py +28 -0
  162. nvmath/distributed/linalg/advanced/__init__.py +8 -0
  163. nvmath/distributed/linalg/advanced/_configuration.py +166 -0
  164. nvmath/distributed/linalg/advanced/matmulmod.py +2908 -0
  165. nvmath/distributed/process_group.py +408 -0
  166. nvmath/distributed/reshape/__init__.py +6 -0
  167. nvmath/distributed/reshape/_configuration.py +39 -0
  168. nvmath/distributed/reshape/reshape.py +1256 -0
  169. nvmath/fft/__init__.py +7 -0
  170. nvmath/fft/_configuration.py +208 -0
  171. nvmath/fft/_exec_utils.py +109 -0
  172. nvmath/fft/_helpers.py +237 -0
  173. nvmath/fft/fft.py +2903 -0
  174. nvmath/internal/__init__.pxd +3 -0
  175. nvmath/internal/__init__.py +10 -0
  176. nvmath/internal/_bindings.cp314-win_amd64.pyd +0 -0
  177. nvmath/internal/_bindings.pxd +12 -0
  178. nvmath/internal/_device_utils.py +54 -0
  179. nvmath/internal/enum_utils.py +142 -0
  180. nvmath/internal/formatters.py +87 -0
  181. nvmath/internal/mem_limit.py +51 -0
  182. nvmath/internal/memory.cp314-win_amd64.pyd +0 -0
  183. nvmath/internal/memory.pxd +10 -0
  184. nvmath/internal/memory.pyi +46 -0
  185. nvmath/internal/ndbuffer/__init__.pxd +3 -0
  186. nvmath/internal/ndbuffer/__init__.py +7 -0
  187. nvmath/internal/ndbuffer/copy_kernel/args.h +34 -0
  188. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/array_view.h +52 -0
  189. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/elementwise.h +68 -0
  190. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/grid_indexer.h +69 -0
  191. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/transposed.h +240 -0
  192. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/type_utils.h +39 -0
  193. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/utils.h +132 -0
  194. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/vec.h +159 -0
  195. nvmath/internal/ndbuffer/copy_kernel/elementwise.h +53 -0
  196. nvmath/internal/ndbuffer/copy_kernel/transposed.h +58 -0
  197. nvmath/internal/ndbuffer/copy_kernel.cp314-win_amd64.pyd +0 -0
  198. nvmath/internal/ndbuffer/copy_kernel.pxd +9 -0
  199. nvmath/internal/ndbuffer/copy_kernel.pyi +9 -0
  200. nvmath/internal/ndbuffer/data_layout.cp314-win_amd64.pyd +0 -0
  201. nvmath/internal/ndbuffer/data_layout.pxd +72 -0
  202. nvmath/internal/ndbuffer/data_layout.pyi +23 -0
  203. nvmath/internal/ndbuffer/jit.cp314-win_amd64.pyd +0 -0
  204. nvmath/internal/ndbuffer/jit.pxd +7 -0
  205. nvmath/internal/ndbuffer/jit.pyi +6 -0
  206. nvmath/internal/ndbuffer/ndbuffer.cp314-win_amd64.pyd +0 -0
  207. nvmath/internal/ndbuffer/ndbuffer.pxd +36 -0
  208. nvmath/internal/ndbuffer/ndbuffer.pyi +41 -0
  209. nvmath/internal/ndbuffer/package_utils.cp314-win_amd64.pyd +0 -0
  210. nvmath/internal/ndbuffer/package_utils.pxd +11 -0
  211. nvmath/internal/ndbuffer/package_utils.pyi +12 -0
  212. nvmath/internal/package_ifc.py +147 -0
  213. nvmath/internal/package_ifc_cuda.py +49 -0
  214. nvmath/internal/package_ifc_cupy.py +49 -0
  215. nvmath/internal/package_ifc_torch.py +31 -0
  216. nvmath/internal/package_wrapper.py +14 -0
  217. nvmath/internal/tensor_ifc.py +194 -0
  218. nvmath/internal/tensor_ifc_cupy.py +241 -0
  219. nvmath/internal/tensor_ifc_ndbuffer.py +153 -0
  220. nvmath/internal/tensor_ifc_numpy.py +183 -0
  221. nvmath/internal/tensor_ifc_torch.py +176 -0
  222. nvmath/internal/tensor_wrapper.py +157 -0
  223. nvmath/internal/typemaps.py +162 -0
  224. nvmath/internal/utils.py +771 -0
  225. nvmath/linalg/__init__.py +46 -0
  226. nvmath/linalg/_internal/__init__.py +3 -0
  227. nvmath/linalg/_internal/algo_cap_ifc.py +82 -0
  228. nvmath/linalg/_internal/algo_config_ifc.py +43 -0
  229. nvmath/linalg/_internal/batch.py +217 -0
  230. nvmath/linalg/_internal/enum_to_tuples.py +64 -0
  231. nvmath/linalg/_internal/epilog_protocol.py +766 -0
  232. nvmath/linalg/_internal/layout.py +624 -0
  233. nvmath/linalg/_internal/matmul_desc_ifc.py +28 -0
  234. nvmath/linalg/_internal/matmul_pref_ifc.py +27 -0
  235. nvmath/linalg/_internal/matrix_layout_ifc.py +26 -0
  236. nvmath/linalg/_internal/typemaps.py +144 -0
  237. nvmath/linalg/_internal/utils.py +134 -0
  238. nvmath/linalg/advanced/__init__.py +8 -0
  239. nvmath/linalg/advanced/_algorithmmod.py +149 -0
  240. nvmath/linalg/advanced/_configuration.py +349 -0
  241. nvmath/linalg/advanced/helpers/__init__.py +5 -0
  242. nvmath/linalg/advanced/helpers/matmul.py +1348 -0
  243. nvmath/linalg/advanced/matmulmod.py +3937 -0
  244. nvmath/linalg/generic/__init__.py +43 -0
  245. nvmath/linalg/generic/_configuration/__init__.py +37 -0
  246. nvmath/linalg/generic/_configuration/layout.py +263 -0
  247. nvmath/linalg/generic/_configuration/match.py +609 -0
  248. nvmath/linalg/generic/_configuration/qualifiers.py +494 -0
  249. nvmath/linalg/generic/_configuration/wrap.py +217 -0
  250. nvmath/linalg/generic/_dtype.py +15 -0
  251. nvmath/linalg/generic/matmulmod.py +1060 -0
  252. nvmath/memory.py +282 -0
  253. nvmath/sparse/__init__.py +38 -0
  254. nvmath/sparse/_internal/__init__.py +21 -0
  255. nvmath/sparse/_internal/common_utils.py +144 -0
  256. nvmath/sparse/_internal/cudss_config_ifc.py +741 -0
  257. nvmath/sparse/_internal/cudss_data_ifc.py +399 -0
  258. nvmath/sparse/_internal/cudss_utils.py +445 -0
  259. nvmath/sparse/_internal/cusparse_utils.py +382 -0
  260. nvmath/sparse/_internal/sparse_bsc_ifc.py +300 -0
  261. nvmath/sparse/_internal/sparse_bsr_ifc.py +303 -0
  262. nvmath/sparse/_internal/sparse_coo_ifc.py +254 -0
  263. nvmath/sparse/_internal/sparse_csc_ifc.py +266 -0
  264. nvmath/sparse/_internal/sparse_csr_ifc.py +266 -0
  265. nvmath/sparse/_internal/sparse_dia_ifc.py +239 -0
  266. nvmath/sparse/_internal/sparse_format_helpers.py +601 -0
  267. nvmath/sparse/_internal/sparse_tensor_ifc.py +121 -0
  268. nvmath/sparse/_internal/sparse_ust_ifc.py +146 -0
  269. nvmath/sparse/_internal/utils.py +56 -0
  270. nvmath/sparse/advanced/__init__.py +7 -0
  271. nvmath/sparse/advanced/_configuration.py +230 -0
  272. nvmath/sparse/advanced/direct_solver.py +1884 -0
  273. nvmath/sparse/generic/__init__.py +7 -0
  274. nvmath/sparse/generic/_configuration.py +129 -0
  275. nvmath/sparse/generic/_helpers.py +137 -0
  276. nvmath/sparse/generic/_thunks.py +21 -0
  277. nvmath/sparse/generic/matmulmod.py +2426 -0
  278. nvmath/sparse/ust/__init__.py +7 -0
  279. nvmath/sparse/ust/_converters.py +378 -0
  280. nvmath/sparse/ust/_drawer.py +552 -0
  281. nvmath/sparse/ust/_emitter.py +553 -0
  282. nvmath/sparse/ust/_jit.py +212 -0
  283. nvmath/sparse/ust/_kernel.py +346 -0
  284. nvmath/sparse/ust/_semiring.py +71 -0
  285. nvmath/sparse/ust/_utils.py +102 -0
  286. nvmath/sparse/ust/interfaces/__init__.py +0 -0
  287. nvmath/sparse/ust/interfaces/torch_interface.py +476 -0
  288. nvmath/sparse/ust/semiring_ops.py +71 -0
  289. nvmath/sparse/ust/tensor.py +1027 -0
  290. nvmath/sparse/ust/tensor_drawer.py +552 -0
  291. nvmath/sparse/ust/tensor_emitter.py +558 -0
  292. nvmath/sparse/ust/tensor_format.py +935 -0
  293. nvmath/sparse/ust/tensor_jit.py +212 -0
  294. nvmath/sparse/ust/tensor_kernel.py +348 -0
  295. nvmath/sparse/ust/tensor_utils.py +380 -0
  296. nvmath/tensor/__init__.py +6 -0
  297. nvmath/tensor/_configuration.py +95 -0
  298. nvmath/tensor/_internal/__init__.py +3 -0
  299. nvmath/tensor/_internal/cutensor_config_ifc.py +247 -0
  300. nvmath/tensor/_internal/cutensor_utils.py +162 -0
  301. nvmath/tensor/_internal/data.py +43 -0
  302. nvmath/tensor/_internal/einsum_parser.py +444 -0
  303. nvmath/tensor/_internal/typemaps.py +96 -0
  304. nvmath/tensor/contract.py +1861 -0
  305. nvmath_python-0.9.0.dist-info/METADATA +127 -0
  306. nvmath_python-0.9.0.dist-info/RECORD +309 -0
  307. nvmath_python-0.9.0.dist-info/WHEEL +5 -0
  308. nvmath_python-0.9.0.dist-info/licenses/LICENSE +177 -0
  309. nvmath_python-0.9.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,29 @@
1
+ # Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from llvmlite import ir
6
+ from numba.core.datamodel.manager import DataModelManager
7
+ from numba.core.datamodel.models import PrimitiveModel
8
+ from numba.cuda.extending import models, register_model, types
9
+
10
+
11
+ class LLVMArray(types.Array):
12
+ def __init__(self, dtype, size):
13
+ super().__init__(dtype, layout="C", ndim=1)
14
+ self.size = size
15
+
16
+ def __str__(self):
17
+ return f"LLVMArray(dtype={self.dtype}, size={self.size})"
18
+
19
+ def __repr__(self):
20
+ return f"LLVMArray(dtype={self.dtype}, size={self.size})"
21
+
22
+
23
+ @register_model(LLVMArray)
24
+ class LLVMArrayModel(models.PrimitiveModel):
25
+ def __init__(self, dmm: DataModelManager, fe_type: LLVMArray):
26
+ dtype_model: PrimitiveModel = dmm.lookup(fe_type.dtype)
27
+ llvm_type = dtype_model.be_type
28
+ be_type = ir.ArrayType(llvm_type, fe_type.size)
29
+ super().__init__(dmm, fe_type, be_type)
@@ -0,0 +1,445 @@
1
+ # Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ """
6
+ Device APIs for RNGs: bit generators and distribution generators.
7
+
8
+ The APIs follow the cuRAND device APIs: https://docs.nvidia.com/cuda/curand/group__DEVICE.html
9
+ """
10
+
11
+ import functools
12
+ import re
13
+ import sys
14
+ import weakref
15
+
16
+ import nvmath.device
17
+ from nvmath.device import curand_kernel, random_helpers
18
+ from nvmath.device import random_states as states
19
+
20
+ try:
21
+ from cuda.core import ObjectCode, Program, ProgramOptions
22
+ except ImportError:
23
+ from cuda.core.experimental import ObjectCode, Program, ProgramOptions
24
+
25
+ from cuda import pathfinder
26
+
27
+ # Common APIs (initialization, bit generation).
28
+ _COMMON_APIS = ["init", "rand", "rand4"]
29
+ _COMMON_APIS_PREFIX = ["curand_", "cu", "cu"]
30
+ _INIT_DOC = """init(..., state)
31
+ Initialize the RNG state.
32
+
33
+ The arguments depend upon the selected bit generator (see the overloads of `curand_init`
34
+ in `cuRAND docs <https://docs.nvidia.com/cuda/curand/group__DEVICE.html>`_).
35
+
36
+ Example:
37
+
38
+ >>> from numba import cuda
39
+ >>> from nvmath.device import random
40
+ >>> compiled_apis = random.Compile(cc=None)
41
+
42
+ We will be working on a grid of 64 blocks, with 64 threads in each.
43
+
44
+ >>> threads = 64
45
+ >>> blocks = 64
46
+ >>> nthreads = blocks * threads
47
+
48
+ Let us show how to use `init` with :class:`nvmath.device.random.StatesPhilox4_32_10`
49
+ states. The same applies to :class:`nvmath.device.random.StatesMRG32k3a` and
50
+ :class:`nvmath.device.random.StatesXORWOW`.
51
+
52
+ First, create an array of states (one per thread) using
53
+ :class:`nvmath.device.random.StatesPhilox4_32_10` constructor.
54
+
55
+ >>> states = random.StatesPhilox4_32_10(nthreads)
56
+
57
+ Define a kernel to initialize the states. Each thread will initialize one element of
58
+ `states`. For the `Philox4_32_10
59
+ <https://docs.nvidia.com/cuda/curand/group__DEVICE.html#group__DEVICE_1ga613d37dacbc50494f2f859ef0d378b8>`_
60
+ generator, the `init` arguments are: `seed`, `subsequence`, `offset`.
61
+
62
+ >>> @cuda.jit(link=compiled_apis.files, extensions=compiled_apis.extension)
63
+ ... def setup(states):
64
+ ... i = cuda.grid(1)
65
+ ... random.init(1234, i, 0, states[i])
66
+
67
+ Run the kernel to initialize the states:
68
+
69
+ >>> setup[blocks, threads](states)
70
+
71
+ Now, you can use the `states` array to generate random numbers using the random
72
+ samplers available.
73
+
74
+ For Sobol' family of quasirandom number generators, initialization is a bit more
75
+ complex as it requires preparing a set of *direction vectors* and *scramble
76
+ constants*. In this example, we will setup
77
+ :class:`nvmath.device.random.StatesScrambledSobol64` states.
78
+
79
+ Direction vectors can be obtained with
80
+ :func:`nvmath.device.random_helpers.get_direction_vectors64`:
81
+
82
+ >>> from nvmath.device import random_helpers
83
+ >>> hostVectors = random_helpers.get_direction_vectors64(
84
+ ... random.random_helpers.DirectionVectorSet.SCRAMBLED_DIRECTION_VECTORS_64_JOEKUO6, nthreads)
85
+ >>> sobolDirectionVectors = cuda.to_device(hostVectors)
86
+
87
+ To get scramble constants, use
88
+ :func:`nvmath.device.random_helpers.get_scramble_constants64`:
89
+
90
+ >>> hostScrambleConstants = random_helpers.get_scramble_constants64(nthreads)
91
+ >>> sobolScrambleConstants = cuda.to_device(hostScrambleConstants)
92
+
93
+ As `init` expects a pointer to direction vectors, we will use `cffi` to obtain it.
94
+
95
+ >>> states = random.StatesScrambledSobol64(nthreads)
96
+ >>>
97
+ >>> import cffi
98
+ >>> ffi = cffi.FFI()
99
+ >>>
100
+ >>> @cuda.jit(link=compiled_apis.files, extensions=compiled_apis.extension)
101
+ ... def setup(sobolDirectionVectors, sobolScrambleConstants, states):
102
+ ... id = cuda.grid(1)
103
+ ... dirptr = ffi.from_buffer(sobolDirectionVectors[id:])
104
+ ... random.init(dirptr, sobolScrambleConstants[id], 1234, states[id])
105
+ """
106
+ _RAND_DOC = """rand(state)
107
+ Generate 32 or 64 bits of randomness depending on the provided bit generator.
108
+
109
+ Args:
110
+ state: a state object corresponding to one of the bit generators.
111
+
112
+ Returns:
113
+ 32 or 64 bits of randomness depending on the provided bit generator.
114
+ """
115
+ _RAND4_DOC = """rand4(state)
116
+ Generate a 4-tuple of 32-bits of randomness from a Philox4_32_10 generator.
117
+
118
+ Args:
119
+ state: a state object corresponding to the Philox4_32_10 generator.
120
+
121
+ Returns:
122
+ A 4-tuple of 32-bits of randomness from a Philox4_32_10 generator as an uint32x4 object.
123
+ """
124
+ _COMMON_APIS_DOC = [_INIT_DOC, _RAND_DOC, _RAND4_DOC]
125
+
126
+ # Bit generator state types.
127
+ _STATES = [
128
+ "StatesMRG32k3a",
129
+ "StatesPhilox4_32_10",
130
+ "StatesSobol32",
131
+ "StatesSobol64",
132
+ "StatesScrambledSobol32",
133
+ "StatesScrambledSobol64",
134
+ "StatesTest",
135
+ "StatesXORWOW",
136
+ ]
137
+
138
+ # Sampling from distributions.
139
+ _SAMPLERS_NORMAL = ["normal", "normal_double", "normal2", "normal2_double", "normal4"]
140
+ _SAMPLERS_LOG_NORMAL = ["log_normal", "log_normal_double", "log_normal2", "log_normal2_double", "log_normal4"]
141
+ _SAMPLERS_POISSON = ["poisson", "poisson4"]
142
+ _SAMPLERS_UNIFORM = ["uniform", "uniform_double", "uniform2_double", "uniform4"]
143
+ _SAMPLERS = _SAMPLERS_NORMAL + _SAMPLERS_LOG_NORMAL + _SAMPLERS_POISSON + _SAMPLERS_UNIFORM
144
+
145
+ # Skip ahead functions.
146
+ _SKIPPERS = ["skipahead", "skipahead_sequence", "skipahead_subsequence"]
147
+
148
+ # Templates.
149
+ _NUMBER_TO_WORD = {"": "a", "2": "two", "4": "four"}
150
+
151
+ _DTYPE_NAME_MAP = {"uint": "uint32", "float": "float32", "double": "float64"}
152
+
153
+ _SAMPLER_DESCRIPTION_TEMPLATE = r"""{name}(state{extra_arguments_str})
154
+ Sample {num_values_word} {dtype_word} from {distribution_word} distribution using the specified bit generator state.
155
+ {arg_docs}
156
+ {sampler_return}
157
+
158
+ Example:
159
+
160
+ The `states` parameter of the kernel below should be an array of already initialized bit generator states.
161
+ See the documentation of :func:`nvmath.device.random.init` for more details on how to create and initialize the
162
+ bit generator states.
163
+
164
+ >>> from numba import cuda
165
+ >>> from nvmath.device import random
166
+ >>> compiled_apis = random.Compile()
167
+ >>> @cuda.jit(link=compiled_apis.files, extensions=compiled_apis.extension)
168
+ ... def kernel(states{extra_arguments_str}):
169
+ ... i = cuda.grid(1)
170
+ ... value = random.{name}(states[i]{extra_arguments_str})
171
+ """
172
+
173
+ _DISTRIBUTION_NAME_SPECIAL_CASES = {
174
+ "poisson": "Poisson",
175
+ "log_normal": "log-normal",
176
+ }
177
+
178
+ _SAMPLER_COMMON_ARGS_TEMPLATE = r"""
179
+
180
+ Args:
181
+ state: a state object corresponding to one of the bit generators.
182
+ """
183
+
184
+ _SAMPLER_RETURN_TEMPLATE = r"""
185
+
186
+ Returns:
187
+ A value of type :class:`{vector_type_description}`.
188
+ """
189
+
190
+ _STATES_DESCRIPTION_TEMPLATE = r"""
191
+ States of {generator_name} bit generator.
192
+
193
+ Once created, the states can be initialized by :func:`nvmath.device.random.init` function.
194
+ See the documentation of :func:`nvmath.device.random.init` for details and examples.
195
+ """
196
+
197
+
198
+ def _wrap(module, orig_name, new_name):
199
+ global functools
200
+
201
+ function = getattr(module, orig_name)
202
+ wrapped = functools.wraps(function)(function)
203
+ wrapped.__name__ = new_name
204
+ return wrapped
205
+
206
+
207
+ def _wrap_sampler(new_name, *, extra_arguments_list: list | None = None, extra_arguments_doc: list[str] | None = None):
208
+ global re
209
+ global curand_kernel
210
+
211
+ if extra_arguments_list is None:
212
+ extra_arguments_list = []
213
+ if extra_arguments_doc is None:
214
+ extra_arguments_doc = []
215
+ # Additional arguments for sampler, if any, other than 'state'.
216
+ num_extra_arguments = len(extra_arguments_list)
217
+ extra_arguments_str = "" if num_extra_arguments == 0 else ", {}".format(", ".join(extra_arguments_list))
218
+
219
+ # Infer data needed for the description template from the name.
220
+ m = re.match(r"([a-z_]+)([24])?(_([\w]+))?", new_name)
221
+ if m is None:
222
+ raise AssertionError(
223
+ f"Random sampler name '{new_name}' is invalid or unexpected. "
224
+ "The regex in nvmath.device.random.py should be updated."
225
+ )
226
+ # Distribution type.
227
+ distribution = m.group(1)
228
+ # Number of return values.
229
+ num_values = "" if m.group(2) is None else m.group(2)
230
+ num_values_word = _NUMBER_TO_WORD[num_values]
231
+ # The dtype of the return values.
232
+ dtype = m.group(4)
233
+ if match_dtype_in_name := re.match("(.*)_(float|double)", distribution):
234
+ # If dtype was parsed as a part of distribution name, extract it.
235
+ distribution = match_dtype_in_name.group(1)
236
+ dtype = match_dtype_in_name.group(2)
237
+ if not dtype:
238
+ # If dtype is not qualified in the name, uint for Poisson, float otherwise.
239
+ dtype = "uint" if distribution == "poisson" else "float"
240
+ distribution_word = _DISTRIBUTION_NAME_SPECIAL_CASES.get(distribution, distribution)
241
+ dtype_word = dtype + "s" if num_values else dtype
242
+
243
+ # Wrap function.
244
+ wrapped = _wrap(curand_kernel, "curand_" + new_name, new_name)
245
+
246
+ # Argument docs
247
+ arg_docs = _SAMPLER_COMMON_ARGS_TEMPLATE
248
+ for extra_argument, extra_argument_doc in zip(extra_arguments_list, extra_arguments_doc, strict=False):
249
+ arg_docs += f" {extra_argument}: {extra_argument_doc}.\n"
250
+
251
+ # Return docs
252
+ vector_type_description = _DTYPE_NAME_MAP[dtype]
253
+ if num_values:
254
+ vector_type_description = "nvmath.device." + vector_type_description + "x" + num_values
255
+ sampler_return = _SAMPLER_RETURN_TEMPLATE.format(vector_type_description=vector_type_description)
256
+
257
+ # Update docstring.
258
+ description = _SAMPLER_DESCRIPTION_TEMPLATE.format(
259
+ name=new_name,
260
+ extra_arguments_str=extra_arguments_str,
261
+ num_values_word=num_values_word,
262
+ distribution_word=distribution_word,
263
+ dtype_word=dtype_word,
264
+ arg_docs=arg_docs,
265
+ sampler_return=sampler_return,
266
+ )
267
+ wrapped.__doc__ = description
268
+
269
+ return wrapped
270
+
271
+
272
+ def _wrap_skipahead(name):
273
+ global re
274
+ global curand_kernel
275
+
276
+ # Infer data needed for the description template from the name.
277
+ m = re.match("skipahead(_([a-z]+))?", name)
278
+ skiptype = "element" if m.group(2) is None else m.group(2)
279
+
280
+ # Wrap function.
281
+ wrapped = _wrap(curand_kernel, name, name)
282
+
283
+ description = f"""{name}(n, state)
284
+ Update the bit generator state to skip ahead ``n`` {skiptype}s.
285
+
286
+ Args:
287
+ n: The number of {skiptype}s to skip ahead.
288
+ state: The bit generator state to update.
289
+ """
290
+ if skiptype != "element":
291
+ description += """
292
+ .. note::
293
+ For the XORWOW and Philox4_32_10 bit generators, the term *sequence* used in the API name and the argument `n`
294
+ essentially refers to the notion of *subsequence* in these algorithms.
295
+ """
296
+
297
+ # Update docstring.
298
+ wrapped.__doc__ = description
299
+
300
+ return wrapped
301
+
302
+
303
+ def _create_symbols():
304
+ global sys
305
+ global curand_kernel
306
+ global c_ext_shim_source
307
+
308
+ random_module = sys.modules[__name__]
309
+
310
+ # Wrap shim function.
311
+ c_ext_shim_source = _wrap(curand_kernel, "c_ext_shim_source", "c_ext_shim_source")
312
+
313
+ # Wrap common APIs.
314
+ for api, prefix, doc in zip(_COMMON_APIS, _COMMON_APIS_PREFIX, _COMMON_APIS_DOC, strict=True):
315
+ function = _wrap(curand_kernel, prefix + api, api)
316
+ function.__doc__ = doc
317
+ setattr(random_module, api, function)
318
+ # TODO: Update doc string for
319
+
320
+ # Wrap skipahead APIs.
321
+ for skipper in _SKIPPERS:
322
+ function = _wrap_skipahead(skipper)
323
+ setattr(random_module, skipper, function)
324
+
325
+ # Samplers with no extra arguments.
326
+ for sampler in _SAMPLERS_NORMAL + _SAMPLERS_UNIFORM:
327
+ function = _wrap_sampler(sampler)
328
+ setattr(random_module, sampler, function)
329
+
330
+ # The log_normal distribution requires two extra arguments.
331
+ extra_arguments_list = ["mean", "stddev"]
332
+ extra_arguments_doc = ["The mean value", "The standard deviation"]
333
+ for sampler in _SAMPLERS_LOG_NORMAL:
334
+ function = _wrap_sampler(sampler, extra_arguments_list=extra_arguments_list, extra_arguments_doc=extra_arguments_doc)
335
+ setattr(random_module, sampler, function)
336
+
337
+ # The poisson distribution requires an extra argument.
338
+ extra_arguments_list = ["Lambda"]
339
+ extra_arguments_doc = ["The parameter characterizing the Poisson distribution"]
340
+ for sampler in _SAMPLERS_POISSON:
341
+ function = _wrap_sampler(sampler, extra_arguments_list=extra_arguments_list, extra_arguments_doc=extra_arguments_doc)
342
+ setattr(random_module, sampler, function)
343
+
344
+
345
+ _create_symbols()
346
+
347
+
348
+ def _wrap_states():
349
+ global sys
350
+ global re
351
+ global states
352
+ global states_arg_handlers
353
+
354
+ random_module = sys.modules[__name__]
355
+
356
+ # Wrap arg handlers extension.
357
+ states_arg_handlers = states.states_arg_handlers
358
+
359
+ for s in _STATES:
360
+ setattr(random_module, s, getattr(states, "curand" + s))
361
+ state = getattr(random_module, s)
362
+ generator_name = re.match("States(.*)", s).group(1)
363
+ state.__doc__ = _STATES_DESCRIPTION_TEMPLATE.format(generator_name=generator_name)
364
+ state.__name__ = s
365
+
366
+
367
+ _wrap_states()
368
+
369
+
370
+ class Compile:
371
+ """
372
+ Compile the random device APIs with the specified compute capability.
373
+
374
+ The ``files`` and ``extension`` attributes should be used as the arguments for
375
+ :py:func:`numba.cuda.jit` decorator in Numba kernels which use random device APIs.
376
+
377
+ Args:
378
+ cc: (optional) the compute capability specified as an object of type
379
+ :py:class:`nvmath.device.ComputeCapability`. If not specified, the default
380
+ compute capability will be used.
381
+
382
+ Example:
383
+ >>> from numba import cuda
384
+ >>> from nvmath.device import random
385
+ >>> compiled_apis = random.Compile()
386
+ >>> @cuda.jit(link=compiled_apis.files, extensions=compiled_apis.extension)
387
+ ... def kernel():
388
+ ... pass # use random device APIs here
389
+ """
390
+
391
+ def __init__(self, cc: nvmath.device.ComputeCapability | None = None):
392
+ global c_ext_shim_source
393
+
394
+ if cc is None:
395
+ cc = nvmath.device.common_cuda.get_default_code_type().cc
396
+ elif not isinstance(cc, nvmath.device.ComputeCapability):
397
+ raise ValueError(
398
+ f"The specified compute capability {cc} is not valid. "
399
+ "It must be an object of type :py:class:`nvmath.device.ComputeCapability`."
400
+ )
401
+ self.cc = cc
402
+
403
+ # Compile APIs to LTO-IR and materialize in 'files' for linking into Numba kernels.
404
+ prog = Program(
405
+ c_ext_shim_source.data, # type: ignore
406
+ "c++",
407
+ ProgramOptions(
408
+ std="c++17",
409
+ arch=f"compute_{cc.major * 10 + cc.minor}",
410
+ device_as_default_execution_space=True,
411
+ link_time_optimization=True,
412
+ gen_opt_lto=True,
413
+ relocatable_device_code=True,
414
+ include_path=[
415
+ pathfinder.find_nvidia_header_directory("cudart"),
416
+ pathfinder.find_nvidia_header_directory("cccl"),
417
+ ],
418
+ ),
419
+ )
420
+ obj = prog.compile("ltoir")
421
+ assert isinstance(obj, ObjectCode)
422
+ self._lto = obj.code
423
+ self._files = [nvmath.device.common.make_binary_tempfile(self._lto, ".ltoir")]
424
+
425
+ self._finalizer = weakref.finalize(self, nvmath.device.common.delete_binary_tempfiles, self.files)
426
+
427
+ @property
428
+ def files(self):
429
+ """
430
+ The data needed to link random device APIs with Numba kernels.
431
+ """
432
+ return [f.name for f in self._files]
433
+
434
+ @property
435
+ def extension(self):
436
+ """
437
+ The extension needed to use random device APIs with Numba kernels.
438
+ """
439
+ global states_arg_handlers
440
+ return states_arg_handlers
441
+
442
+
443
+ __all__ = ["Compile", "random_helpers"] + _COMMON_APIS + _SAMPLERS + _SKIPPERS + _STATES # type: ignore # noqa: PLE0605
444
+
445
+ del functools, re, curand_kernel, states
@@ -0,0 +1,23 @@
1
+ # Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ """
6
+ Helper host APIs for random device APIs.
7
+ """
8
+
9
+ __all__ = [
10
+ "DirectionVectorSet",
11
+ "get_direction_vectors32",
12
+ "get_scramble_constants32",
13
+ "get_direction_vectors64",
14
+ "get_scramble_constants64",
15
+ ]
16
+
17
+ from nvmath.bindings.curand import ( # type: ignore
18
+ DirectionVectorSet,
19
+ get_direction_vectors32,
20
+ get_direction_vectors64,
21
+ get_scramble_constants32,
22
+ get_scramble_constants64,
23
+ )
@@ -0,0 +1,187 @@
1
+ # Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ import operator
6
+
7
+ import numpy as np
8
+ from llvmlite import ir
9
+ from numba import cuda, types
10
+ from numba.core.typing.templates import AbstractTemplate, signature
11
+ from numba.cuda.cudadecl import register_global
12
+ from numba.cuda.cudaimpl import lower
13
+ from numba.extending import models, register_model, typeof_impl
14
+
15
+ from nvmath.device import curand_kernel
16
+
17
+ xorwow_dtype = np.dtype(
18
+ [
19
+ ("d", np.uint32),
20
+ ("v", np.uint32, (5,)),
21
+ ("boxmuller_flag", np.int32),
22
+ ("boxmuller_flag_double", np.int32),
23
+ ("boxmuller_extra", np.float32),
24
+ ("boxmuller_extra_double", np.float64),
25
+ ],
26
+ align=True,
27
+ )
28
+ test_dtype = np.dtype([("v", np.uint32)], align=True)
29
+ mrg32k3a_dtype = np.dtype(
30
+ [
31
+ ("s1", np.uint32, (3,)),
32
+ ("s2", np.uint32, (3,)),
33
+ ("boxmuller_flag", np.int32),
34
+ ("boxmuller_flag_double", np.int32),
35
+ ("boxmuller_extra", np.float32),
36
+ ("boxmuller_extra_double", np.float64),
37
+ ],
38
+ align=True,
39
+ )
40
+ sobol32_dtype = np.dtype(
41
+ [("i", np.uint32), ("x", np.uint32), ("c", np.uint32), ("direction_vectors", np.int32, (32,))], align=True
42
+ )
43
+ scrambled_sobol32_dtype = np.dtype(
44
+ [("i", np.uint32), ("x", np.uint32), ("c", np.uint32), ("direction_vectors", np.int32, (32,))], align=True
45
+ )
46
+ sobol64_dtype = np.dtype(
47
+ [("i", np.uint64), ("x", np.uint64), ("c", np.uint64), ("direction_vectors", np.int64, (64,))], align=True
48
+ )
49
+ scrambled_sobol64_dtype = np.dtype(
50
+ [("i", np.uint64), ("x", np.uint64), ("c", np.uint64), ("direction_vectors", np.int64, (64,))], align=True
51
+ )
52
+ philox4_32_10_dtype = np.dtype(
53
+ [
54
+ ("ctr", np.uint32, (4,)),
55
+ ("output", np.uint32, (4,)),
56
+ ("key", np.uint32, (2,)),
57
+ ("STATE", np.uint32),
58
+ ("boxmuller_flag", np.int32),
59
+ ("boxmuller_flag_double", np.int32),
60
+ ("boxmuller_extra", np.float32),
61
+ ("boxmuller_extra_double", np.float64),
62
+ ],
63
+ align=True,
64
+ )
65
+
66
+ NP_DTYPES = {
67
+ "curandStateXORWOW": xorwow_dtype,
68
+ "curandStateTest": test_dtype,
69
+ "curandStateMRG32k3a": mrg32k3a_dtype,
70
+ "curandStateSobol32": sobol32_dtype,
71
+ "curandStateScrambledSobol32": scrambled_sobol32_dtype,
72
+ "curandStateSobol64": sobol64_dtype,
73
+ "curandStateScrambledSobol64": scrambled_sobol64_dtype,
74
+ "curandStatePhilox4_32_10": philox4_32_10_dtype,
75
+ }
76
+
77
+
78
+ def make_curand_states(name: str):
79
+ """Create a boxed curand states object to represent an array of curand state.
80
+ Should invoke after creating the numba types for each curand state.
81
+ """
82
+
83
+ curand_state_name = name
84
+
85
+ state_ty = getattr(curand_kernel, f"_type_{curand_state_name}")
86
+
87
+ curand_states_name = curand_state_name.replace("State", "States")
88
+
89
+ # cuRAND state type as a NumPy dtype - this mirrors the state defined in
90
+ # curand_kernel.h. Can be used to inspect the state through the device array
91
+ # held by CurandStates.
92
+
93
+ curandStateDtype = NP_DTYPES[curand_state_name]
94
+
95
+ # Hold an array of cuRAND states - somewhat analogous to a curandState* in
96
+ # C/C++.
97
+
98
+ class CurandStates:
99
+ def __init__(self, n):
100
+ self._array = cuda.device_array(n, dtype=curandStateDtype)
101
+
102
+ @property
103
+ def data(self):
104
+ return self._array.__cuda_array_interface__["data"][0]
105
+
106
+ CurandStates.__name__ = curand_states_name
107
+
108
+ class CurandStatePointer(types.Type):
109
+ def __init__(self, name):
110
+ self.dtype = state_ty
111
+ super().__init__(name=name)
112
+
113
+ curand_state_pointer = CurandStatePointer(curand_states_name + "*")
114
+
115
+ @typeof_impl.register(CurandStates)
116
+ def typeof_curand_states(val, c):
117
+ return curand_state_pointer
118
+
119
+ @register_global(operator.getitem)
120
+ class CurandStatesPointerGetItem(AbstractTemplate):
121
+ def generic(self, args, kws):
122
+ assert not kws
123
+ [ptr, idx] = args
124
+ if ptr == curand_state_pointer:
125
+ return signature(types.CPointer(state_ty), curand_state_pointer, types.int64)
126
+
127
+ register_model(CurandStatePointer)(models.PointerModel)
128
+
129
+ @lower(operator.getitem, curand_state_pointer, types.int64)
130
+ def lower_curand_states_getitem(context, builder, sig, args):
131
+ [ptr, idx] = args
132
+
133
+ # Working out my own GEP
134
+ ptrint = builder.ptrtoint(ptr, ir.IntType(64))
135
+ itemsize = curandStateDtype.itemsize
136
+ offset = builder.mul(idx, context.get_constant(types.int64, itemsize))
137
+ ptrint = builder.add(ptrint, offset)
138
+ ptr = builder.inttoptr(ptrint, ptr.type)
139
+ return ptr
140
+
141
+ # Argument handling. When a CurandStatePointer is passed into a kernel, we
142
+ # really only need to pass the pointer to the data, not the whole underlying
143
+ # array structure. Our handler here transforms these arguments into a uint64
144
+ # holding the pointer.
145
+
146
+ class CurandStateArgHandler:
147
+ def prepare_args(self, ty, val, **kwargs):
148
+ if isinstance(val, CurandStates):
149
+ assert ty == curand_state_pointer
150
+ return types.uint64, val.data
151
+ else:
152
+ return ty, val
153
+
154
+ curand_state_arg_handler = CurandStateArgHandler()
155
+
156
+ return CurandStates, curand_state_arg_handler
157
+
158
+
159
+ curandStates = [
160
+ "curandStateTest",
161
+ "curandStateXORWOW",
162
+ "curandStateMRG32k3a",
163
+ "curandStateSobol32",
164
+ "curandStateScrambledSobol32",
165
+ "curandStateSobol64",
166
+ "curandStateScrambledSobol64",
167
+ "curandStatePhilox4_32_10",
168
+ # Require additional type parsing of mtgp32_params_fast and mtgp32_kernel_params
169
+ # "curandStateMtgp32",
170
+ ]
171
+
172
+ numpy_curand_states = []
173
+ states_arg_handlers = []
174
+
175
+ for state in curandStates:
176
+ states_obj, arg_handler = make_curand_states(state)
177
+ numpy_curand_states.append(states_obj)
178
+ states_arg_handlers.append(arg_handler)
179
+
180
+
181
+ # Export
182
+ globals().update({s.__name__: s for s in numpy_curand_states})
183
+ globals().update({"states_arg_handlers": states_arg_handlers})
184
+
185
+ __all__ = list( # noqa: F822
186
+ {s.__name__ for s in numpy_curand_states} | {"states_arg_handlers"}
187
+ )