pytensor 2.18.0__tar.gz → 2.18.2__tar.gz

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 (414) hide show
  1. {pytensor-2.18.0 → pytensor-2.18.2}/PKG-INFO +1 -1
  2. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/using_params.rst +17 -21
  3. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/_version.py +3 -3
  4. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/compile/function/types.py +10 -4
  5. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/compile/profiling.py +4 -0
  6. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/graph/basic.py +5 -12
  7. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/graph/op.py +9 -56
  8. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/graph/replace.py +14 -13
  9. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/c/basic.py +11 -2
  10. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/c/cmodule.py +39 -12
  11. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/c/interface.py +24 -1
  12. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/c/op.py +2 -2
  13. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/jax/dispatch/nlinalg.py +1 -3
  14. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/numba/dispatch/basic.py +7 -16
  15. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/raise_op.py +1 -1
  16. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/scan/op.py +1 -1
  17. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/scan/rewriting.py +42 -11
  18. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/basic.py +84 -16
  19. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/blas.py +81 -152
  20. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/blockwise.py +33 -9
  21. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/elemwise.py +1 -1
  22. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/extra_ops.py +7 -3
  23. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/math.py +19 -5
  24. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/rewriting/basic.py +12 -11
  25. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/rewriting/blas.py +33 -8
  26. pytensor-2.18.2/pytensor/tensor/rewriting/blockwise.py +201 -0
  27. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/rewriting/linalg.py +10 -3
  28. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/rewriting/math.py +92 -160
  29. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/rewriting/shape.py +16 -0
  30. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/rewriting/subtensor.py +109 -26
  31. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/rewriting/uncanonicalize.py +1 -1
  32. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/shape.py +36 -20
  33. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/subtensor.py +18 -1
  34. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor.egg-info/PKG-INFO +1 -1
  35. {pytensor-2.18.0 → pytensor-2.18.2}/scripts/mypy-failing.txt +0 -1
  36. {pytensor-2.18.0 → pytensor-2.18.2}/tests/test_printing.py +17 -14
  37. pytensor-2.18.0/pytensor/tensor/rewriting/blockwise.py +0 -51
  38. {pytensor-2.18.0 → pytensor-2.18.2}/LICENSE.txt +0 -0
  39. {pytensor-2.18.0 → pytensor-2.18.2}/MANIFEST.in +0 -0
  40. {pytensor-2.18.0 → pytensor-2.18.2}/README.rst +0 -0
  41. {pytensor-2.18.0 → pytensor-2.18.2}/bin/__init__.py +0 -0
  42. {pytensor-2.18.0 → pytensor-2.18.2}/bin/pytensor-cache +0 -0
  43. {pytensor-2.18.0 → pytensor-2.18.2}/bin/pytensor_cache.py +0 -0
  44. {pytensor-2.18.0 → pytensor-2.18.2}/doc/.templates/PLACEHOLDER +0 -0
  45. {pytensor-2.18.0 → pytensor-2.18.2}/doc/.templates/layout.html +0 -0
  46. {pytensor-2.18.0 → pytensor-2.18.2}/doc/LICENSE.txt +0 -0
  47. {pytensor-2.18.0 → pytensor-2.18.2}/doc/README.md +0 -0
  48. {pytensor-2.18.0 → pytensor-2.18.2}/doc/acknowledgement.rst +0 -0
  49. {pytensor-2.18.0 → pytensor-2.18.2}/doc/bcast.png +0 -0
  50. {pytensor-2.18.0 → pytensor-2.18.2}/doc/bcast.svg +0 -0
  51. {pytensor-2.18.0 → pytensor-2.18.2}/doc/conf.py +0 -0
  52. {pytensor-2.18.0 → pytensor-2.18.2}/doc/core_development_guide.rst +0 -0
  53. {pytensor-2.18.0 → pytensor-2.18.2}/doc/css.inc +0 -0
  54. {pytensor-2.18.0 → pytensor-2.18.2}/doc/dev_start_guide.rst +0 -0
  55. {pytensor-2.18.0 → pytensor-2.18.2}/doc/environment.yml +0 -0
  56. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/apply.png +0 -0
  57. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/apply.svg +0 -0
  58. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/apply2.svg +0 -0
  59. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/creating_a_c_op.rst +0 -0
  60. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/creating_a_numba_jax_op.rst +0 -0
  61. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/creating_an_op.rst +0 -0
  62. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/ctype.rst +0 -0
  63. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/extending_faq.rst +0 -0
  64. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/extending_pytensor_solution_1.py +0 -0
  65. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/graph_rewriting.rst +0 -0
  66. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/graphstructures.rst +0 -0
  67. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/index.rst +0 -0
  68. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/inplace.rst +0 -0
  69. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/op.rst +0 -0
  70. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/other_ops.rst +0 -0
  71. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/pics/symbolic_graph_opt.png +0 -0
  72. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/pics/symbolic_graph_unopt.png +0 -0
  73. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/pipeline.rst +0 -0
  74. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/scan.rst +0 -0
  75. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/tips.rst +0 -0
  76. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/type.rst +0 -0
  77. {pytensor-2.18.0 → pytensor-2.18.2}/doc/extending/unittest.rst +0 -0
  78. {pytensor-2.18.0 → pytensor-2.18.2}/doc/faq.rst +0 -0
  79. {pytensor-2.18.0 → pytensor-2.18.2}/doc/generate_dtype_tensor_table.py +0 -0
  80. {pytensor-2.18.0 → pytensor-2.18.2}/doc/glossary.rst +0 -0
  81. {pytensor-2.18.0 → pytensor-2.18.2}/doc/images/Elman_srnn.png +0 -0
  82. {pytensor-2.18.0 → pytensor-2.18.2}/doc/images/PyTensor_RGB.svg +0 -0
  83. {pytensor-2.18.0 → pytensor-2.18.2}/doc/images/blocksparse.png +0 -0
  84. {pytensor-2.18.0 → pytensor-2.18.2}/doc/images/lstm.png +0 -0
  85. {pytensor-2.18.0 → pytensor-2.18.2}/doc/images/lstm_memorycell.png +0 -0
  86. {pytensor-2.18.0 → pytensor-2.18.2}/doc/images/talk2010.gif +0 -0
  87. {pytensor-2.18.0 → pytensor-2.18.2}/doc/images/talk2010.png +0 -0
  88. {pytensor-2.18.0 → pytensor-2.18.2}/doc/index.rst +0 -0
  89. {pytensor-2.18.0 → pytensor-2.18.2}/doc/install.rst +0 -0
  90. {pytensor-2.18.0 → pytensor-2.18.2}/doc/internal/how_to_release.rst +0 -0
  91. {pytensor-2.18.0 → pytensor-2.18.2}/doc/internal/index.rst +0 -0
  92. {pytensor-2.18.0 → pytensor-2.18.2}/doc/internal/metadocumentation.rst +0 -0
  93. {pytensor-2.18.0 → pytensor-2.18.2}/doc/introduction.rst +0 -0
  94. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/compile/debugmode.rst +0 -0
  95. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/compile/function.rst +0 -0
  96. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/compile/index.rst +0 -0
  97. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/compile/io.rst +0 -0
  98. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/compile/mode.rst +0 -0
  99. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/compile/nanguardmode.rst +0 -0
  100. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/compile/opfromgraph.rst +0 -0
  101. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/compile/ops.rst +0 -0
  102. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/compile/profilemode.rst +0 -0
  103. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/compile/shared.rst +0 -0
  104. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/config.rst +0 -0
  105. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/d3viz/examples/d3viz/css/d3-context-menu.css +0 -0
  106. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/d3viz/examples/d3viz/css/d3viz.css +0 -0
  107. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/d3viz/examples/d3viz/js/d3-context-menu.js +0 -0
  108. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/d3viz/examples/d3viz/js/d3.v3.min.js +0 -0
  109. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/d3viz/examples/d3viz/js/d3viz.js +0 -0
  110. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/d3viz/examples/d3viz/js/dagre-d3.min.js +0 -0
  111. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/d3viz/examples/d3viz/js/graphlib-dot.min.js +0 -0
  112. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/d3viz/examples/mlp.html +0 -0
  113. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/d3viz/examples/mlp.png +0 -0
  114. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/d3viz/examples/mlp2.html +0 -0
  115. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/d3viz/examples/mlp2.pdf +0 -0
  116. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/d3viz/examples/mlp2.png +0 -0
  117. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/d3viz/examples/ofg.html +0 -0
  118. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/d3viz/examples/ofg2.html +0 -0
  119. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/d3viz/index.ipynb +0 -0
  120. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/d3viz/index.rst +0 -0
  121. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/d3viz/index_files/index_10_0.png +0 -0
  122. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/d3viz/index_files/index_11_0.png +0 -0
  123. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/d3viz/index_files/index_24_0.png +0 -0
  124. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/d3viz/index_files/index_25_0.png +0 -0
  125. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/gradient.rst +0 -0
  126. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/graph/features.rst +0 -0
  127. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/graph/fgraph.rst +0 -0
  128. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/graph/graph.rst +0 -0
  129. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/graph/index.rst +0 -0
  130. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/graph/op.rst +0 -0
  131. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/graph/type.rst +0 -0
  132. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/graph/utils.rst +0 -0
  133. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/index.rst +0 -0
  134. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/misc/pkl_utils.rst +0 -0
  135. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/printing.rst +0 -0
  136. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/sandbox/index.rst +0 -0
  137. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/sandbox/linalg.rst +0 -0
  138. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/scalar/index.rst +0 -0
  139. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/scan.rst +0 -0
  140. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/sparse/index.rst +0 -0
  141. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/sparse/sandbox.rst +0 -0
  142. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/tensor/basic.rst +0 -0
  143. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/tensor/basic_opt.rst +0 -0
  144. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/tensor/bcast.png +0 -0
  145. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/tensor/bcast.svg +0 -0
  146. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/tensor/conv.rst +0 -0
  147. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/tensor/elemwise.rst +0 -0
  148. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/tensor/extra_ops.rst +0 -0
  149. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/tensor/fft.rst +0 -0
  150. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/tensor/index.rst +0 -0
  151. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/tensor/io.rst +0 -0
  152. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/tensor/math_opt.rst +0 -0
  153. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/tensor/nlinalg.rst +0 -0
  154. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/tensor/plot_fft.png +0 -0
  155. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/tensor/random/basic.rst +0 -0
  156. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/tensor/random/index.rst +0 -0
  157. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/tensor/random/utils.rst +0 -0
  158. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/tensor/slinalg.rst +0 -0
  159. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/tensor/utils.rst +0 -0
  160. {pytensor-2.18.0 → pytensor-2.18.2}/doc/library/typed_list.rst +0 -0
  161. {pytensor-2.18.0 → pytensor-2.18.2}/doc/links.rst +0 -0
  162. {pytensor-2.18.0 → pytensor-2.18.2}/doc/optimizations.rst +0 -0
  163. {pytensor-2.18.0 → pytensor-2.18.2}/doc/pylintrc +0 -0
  164. {pytensor-2.18.0 → pytensor-2.18.2}/doc/sandbox/ccodegen.rst +0 -0
  165. {pytensor-2.18.0 → pytensor-2.18.2}/doc/sandbox/compilation.rst +0 -0
  166. {pytensor-2.18.0 → pytensor-2.18.2}/doc/sandbox/debugging_with_stepmode.rst +0 -0
  167. {pytensor-2.18.0 → pytensor-2.18.2}/doc/sandbox/elemwise_compiler.rst +0 -0
  168. {pytensor-2.18.0 → pytensor-2.18.2}/doc/sandbox/function.rst +0 -0
  169. {pytensor-2.18.0 → pytensor-2.18.2}/doc/sandbox/functional.rst +0 -0
  170. {pytensor-2.18.0 → pytensor-2.18.2}/doc/sandbox/how_to_make_ops.rst +0 -0
  171. {pytensor-2.18.0 → pytensor-2.18.2}/doc/sandbox/index.rst +0 -0
  172. {pytensor-2.18.0 → pytensor-2.18.2}/doc/sandbox/index2.rst +0 -0
  173. {pytensor-2.18.0 → pytensor-2.18.2}/doc/sandbox/interactive_debugger.rst +0 -0
  174. {pytensor-2.18.0 → pytensor-2.18.2}/doc/sandbox/logistic_regression_example.rst +0 -0
  175. {pytensor-2.18.0 → pytensor-2.18.2}/doc/sandbox/performance.rst +0 -0
  176. {pytensor-2.18.0 → pytensor-2.18.2}/doc/sandbox/randomnumbers.rst +0 -0
  177. {pytensor-2.18.0 → pytensor-2.18.2}/doc/sandbox/rethinkccodegen.rst +0 -0
  178. {pytensor-2.18.0 → pytensor-2.18.2}/doc/sandbox/sandbox.rst +0 -0
  179. {pytensor-2.18.0 → pytensor-2.18.2}/doc/sandbox/software.rst +0 -0
  180. {pytensor-2.18.0 → pytensor-2.18.2}/doc/sandbox/sparse.rst +0 -0
  181. {pytensor-2.18.0 → pytensor-2.18.2}/doc/sandbox/tensoroptools.rst +0 -0
  182. {pytensor-2.18.0 → pytensor-2.18.2}/doc/scripts/docgen.py +0 -0
  183. {pytensor-2.18.0 → pytensor-2.18.2}/doc/troubleshooting.rst +0 -0
  184. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/adding.rst +0 -0
  185. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/adding_solution_1.py +0 -0
  186. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/aliasing.rst +0 -0
  187. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/apply.png +0 -0
  188. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/apply.svg +0 -0
  189. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/bcast.png +0 -0
  190. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/broadcasting.rst +0 -0
  191. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/conditions.rst +0 -0
  192. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/debug_faq.rst +0 -0
  193. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/dlogistic.png +0 -0
  194. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/examples.rst +0 -0
  195. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/faq_tutorial.rst +0 -0
  196. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/gradients.rst +0 -0
  197. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/index.rst +0 -0
  198. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/loading_and_saving.rst +0 -0
  199. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/logistic.gp +0 -0
  200. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/logistic.png +0 -0
  201. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/loop.rst +0 -0
  202. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/loop_solution_1.py +0 -0
  203. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/modes.rst +0 -0
  204. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/modes_solution_1.py +0 -0
  205. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/multi_cores.rst +0 -0
  206. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/nan_tutorial.rst +0 -0
  207. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/pics/d3viz.png +0 -0
  208. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/pics/logreg_pydotprint_predict.png +0 -0
  209. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/pics/logreg_pydotprint_prediction.png +0 -0
  210. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/pics/logreg_pydotprint_train.png +0 -0
  211. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/printing_drawing.rst +0 -0
  212. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/profiling.rst +0 -0
  213. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/profiling_example.py +0 -0
  214. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/profiling_example_out.prof +0 -0
  215. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/shape_info.rst +0 -0
  216. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/sparse.rst +0 -0
  217. {pytensor-2.18.0 → pytensor-2.18.2}/doc/tutorial/symbolic_graphs.rst +0 -0
  218. {pytensor-2.18.0 → pytensor-2.18.2}/doc/user_guide.rst +0 -0
  219. {pytensor-2.18.0 → pytensor-2.18.2}/pyproject.toml +0 -0
  220. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/__init__.py +0 -0
  221. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/bin/__init__.py +0 -0
  222. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/bin/pytensor_cache.py +0 -0
  223. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/breakpoint.py +0 -0
  224. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/compile/__init__.py +0 -0
  225. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/compile/builders.py +0 -0
  226. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/compile/compiledir.py +0 -0
  227. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/compile/compilelock.py +0 -0
  228. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/compile/debugmode.py +0 -0
  229. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/compile/function/__init__.py +0 -0
  230. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/compile/function/pfunc.py +0 -0
  231. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/compile/io.py +0 -0
  232. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/compile/mode.py +0 -0
  233. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/compile/monitormode.py +0 -0
  234. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/compile/nanguardmode.py +0 -0
  235. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/compile/ops.py +0 -0
  236. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/compile/sharedvalue.py +0 -0
  237. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/configdefaults.py +0 -0
  238. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/configparser.py +0 -0
  239. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/d3viz/__init__.py +0 -0
  240. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/d3viz/css/d3-context-menu.css +0 -0
  241. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/d3viz/css/d3viz.css +0 -0
  242. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/d3viz/d3viz.py +0 -0
  243. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/d3viz/formatting.py +0 -0
  244. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/d3viz/js/d3-context-menu.js +0 -0
  245. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/d3viz/js/d3.v3.min.js +0 -0
  246. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/d3viz/js/d3viz.js +0 -0
  247. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/d3viz/js/dagre-d3.min.js +0 -0
  248. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/d3viz/js/graphlib-dot.min.js +0 -0
  249. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/gradient.py +0 -0
  250. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/graph/__init__.py +0 -0
  251. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/graph/destroyhandler.py +0 -0
  252. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/graph/features.py +0 -0
  253. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/graph/fg.py +0 -0
  254. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/graph/null_type.py +0 -0
  255. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/graph/rewriting/__init__.py +0 -0
  256. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/graph/rewriting/basic.py +0 -0
  257. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/graph/rewriting/db.py +0 -0
  258. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/graph/rewriting/kanren.py +0 -0
  259. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/graph/rewriting/unify.py +0 -0
  260. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/graph/rewriting/utils.py +0 -0
  261. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/graph/type.py +0 -0
  262. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/graph/utils.py +0 -0
  263. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/ifelse.py +0 -0
  264. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/__init__.py +0 -0
  265. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/basic.py +0 -0
  266. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/c/__init__.py +0 -0
  267. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/c/c_code/lazylinker_c.c +0 -0
  268. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/c/c_code/pytensor_mod_helper.h +0 -0
  269. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/c/cutils.py +0 -0
  270. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/c/cvm.py +0 -0
  271. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/c/exceptions.py +0 -0
  272. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/c/lazylinker_c.py +0 -0
  273. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/c/params_type.py +0 -0
  274. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/c/type.py +0 -0
  275. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/jax/__init__.py +0 -0
  276. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/jax/dispatch/__init__.py +0 -0
  277. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/jax/dispatch/basic.py +0 -0
  278. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/jax/dispatch/blockwise.py +0 -0
  279. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/jax/dispatch/elemwise.py +0 -0
  280. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/jax/dispatch/extra_ops.py +0 -0
  281. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/jax/dispatch/random.py +0 -0
  282. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/jax/dispatch/scalar.py +0 -0
  283. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/jax/dispatch/scan.py +0 -0
  284. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/jax/dispatch/shape.py +0 -0
  285. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/jax/dispatch/slinalg.py +0 -0
  286. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/jax/dispatch/sparse.py +0 -0
  287. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/jax/dispatch/subtensor.py +0 -0
  288. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/jax/dispatch/tensor_basic.py +0 -0
  289. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/jax/linker.py +0 -0
  290. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/numba/__init__.py +0 -0
  291. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/numba/dispatch/__init__.py +0 -0
  292. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/numba/dispatch/cython_support.py +0 -0
  293. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/numba/dispatch/elemwise.py +0 -0
  294. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/numba/dispatch/elemwise_codegen.py +0 -0
  295. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/numba/dispatch/extra_ops.py +0 -0
  296. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/numba/dispatch/nlinalg.py +0 -0
  297. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/numba/dispatch/random.py +0 -0
  298. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/numba/dispatch/scalar.py +0 -0
  299. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/numba/dispatch/scan.py +0 -0
  300. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/numba/dispatch/slinalg.py +0 -0
  301. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/numba/dispatch/sparse.py +0 -0
  302. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/numba/dispatch/tensor_basic.py +0 -0
  303. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/numba/linker.py +0 -0
  304. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/utils.py +0 -0
  305. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/link/vm.py +0 -0
  306. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/misc/__init__.py +0 -0
  307. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/misc/check_blas.py +0 -0
  308. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/misc/check_blas_many.sh +0 -0
  309. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/misc/check_duplicate_key.py +0 -0
  310. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/misc/elemwise_openmp_speedup.py +0 -0
  311. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/misc/elemwise_time_test.py +0 -0
  312. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/misc/frozendict.py +0 -0
  313. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/misc/may_share_memory.py +0 -0
  314. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/misc/ordered_set.py +0 -0
  315. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/misc/pkl_utils.py +0 -0
  316. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/misc/safe_asarray.py +0 -0
  317. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/printing.py +0 -0
  318. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/py.typed +0 -0
  319. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/scalar/__init__.py +0 -0
  320. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/scalar/basic.py +0 -0
  321. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/scalar/c_code/Faddeeva.cc +0 -0
  322. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/scalar/c_code/Faddeeva.hh +0 -0
  323. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/scalar/c_code/gamma.c +0 -0
  324. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/scalar/loop.py +0 -0
  325. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/scalar/math.py +0 -0
  326. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/scalar/sharedvar.py +0 -0
  327. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/scan/__init__.py +0 -0
  328. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/scan/basic.py +0 -0
  329. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/scan/checkpoints.py +0 -0
  330. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/scan/scan_perform.pyx +0 -0
  331. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/scan/scan_perform_ext.py +0 -0
  332. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/scan/utils.py +0 -0
  333. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/scan/views.py +0 -0
  334. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/sparse/__init__.py +0 -0
  335. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/sparse/basic.py +0 -0
  336. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/sparse/rewriting.py +0 -0
  337. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/sparse/sandbox/__init__.py +0 -0
  338. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/sparse/sandbox/sp.py +0 -0
  339. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/sparse/sandbox/sp2.py +0 -0
  340. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/sparse/sharedvar.py +0 -0
  341. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/sparse/type.py +0 -0
  342. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/sparse/utils.py +0 -0
  343. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/__init__.py +0 -0
  344. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/blas_c.py +0 -0
  345. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/blas_headers.py +0 -0
  346. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/blas_scipy.py +0 -0
  347. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/c_code/alt_blas_common.h +0 -0
  348. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/c_code/alt_blas_template.c +0 -0
  349. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/c_code/dimshuffle.c +0 -0
  350. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/conv/__init__.py +0 -0
  351. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/conv/abstract_conv.py +0 -0
  352. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/elemwise_cgen.py +0 -0
  353. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/exceptions.py +0 -0
  354. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/fft.py +0 -0
  355. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/fourier.py +0 -0
  356. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/functional.py +0 -0
  357. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/inplace.py +0 -0
  358. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/io.py +0 -0
  359. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/linalg.py +0 -0
  360. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/nlinalg.py +0 -0
  361. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/random/__init__.py +0 -0
  362. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/random/basic.py +0 -0
  363. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/random/op.py +0 -0
  364. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/random/rewriting/__init__.py +0 -0
  365. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/random/rewriting/basic.py +0 -0
  366. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/random/rewriting/jax.py +0 -0
  367. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/random/type.py +0 -0
  368. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/random/utils.py +0 -0
  369. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/random/var.py +0 -0
  370. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/rewriting/__init__.py +0 -0
  371. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/rewriting/blas_c.py +0 -0
  372. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/rewriting/blas_scipy.py +0 -0
  373. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/rewriting/elemwise.py +0 -0
  374. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/rewriting/extra_ops.py +0 -0
  375. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/rewriting/jax.py +0 -0
  376. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/rewriting/special.py +0 -0
  377. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/sharedvar.py +0 -0
  378. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/slinalg.py +0 -0
  379. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/sort.py +0 -0
  380. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/special.py +0 -0
  381. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/type.py +0 -0
  382. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/type_other.py +0 -0
  383. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/utils.py +0 -0
  384. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/var.py +0 -0
  385. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/variable.py +0 -0
  386. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/tensor/xlogx.py +0 -0
  387. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/typed_list/__init__.py +0 -0
  388. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/typed_list/basic.py +0 -0
  389. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/typed_list/rewriting.py +0 -0
  390. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/typed_list/type.py +0 -0
  391. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/updates.py +0 -0
  392. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/utils.py +0 -0
  393. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor/version.py +0 -0
  394. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor.egg-info/SOURCES.txt +0 -0
  395. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor.egg-info/dependency_links.txt +0 -0
  396. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor.egg-info/entry_points.txt +0 -0
  397. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor.egg-info/requires.txt +0 -0
  398. {pytensor-2.18.0 → pytensor-2.18.2}/pytensor.egg-info/top_level.txt +0 -0
  399. {pytensor-2.18.0 → pytensor-2.18.2}/scripts/downstream_pr.sh +0 -0
  400. {pytensor-2.18.0 → pytensor-2.18.2}/scripts/upstream_pr.sh +0 -0
  401. {pytensor-2.18.0 → pytensor-2.18.2}/setup.cfg +0 -0
  402. {pytensor-2.18.0 → pytensor-2.18.2}/setup.py +0 -0
  403. {pytensor-2.18.0 → pytensor-2.18.2}/tests/link/c/c_code/test_cenum.h +0 -0
  404. {pytensor-2.18.0 → pytensor-2.18.2}/tests/link/c/c_code/test_quadratic_function.c +0 -0
  405. {pytensor-2.18.0 → pytensor-2.18.2}/tests/tensor/conv/c_code/corr3d_gemm.c +0 -0
  406. {pytensor-2.18.0 → pytensor-2.18.2}/tests/tensor/conv/c_code/corr_gemm.c +0 -0
  407. {pytensor-2.18.0 → pytensor-2.18.2}/tests/test_breakpoint.py +0 -0
  408. {pytensor-2.18.0 → pytensor-2.18.2}/tests/test_config.py +0 -0
  409. {pytensor-2.18.0 → pytensor-2.18.2}/tests/test_gradient.py +0 -0
  410. {pytensor-2.18.0 → pytensor-2.18.2}/tests/test_ifelse.py +0 -0
  411. {pytensor-2.18.0 → pytensor-2.18.2}/tests/test_raise_op.py +0 -0
  412. {pytensor-2.18.0 → pytensor-2.18.2}/tests/test_rop.py +0 -0
  413. {pytensor-2.18.0 → pytensor-2.18.2}/tests/test_updates.py +0 -0
  414. {pytensor-2.18.0 → pytensor-2.18.2}/versioneer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pytensor
3
- Version: 2.18.0
3
+ Version: 2.18.2
4
4
  Summary: Optimizing compiler for evaluating mathematical expressions on CPUs and GPUs.
5
5
  Author-email: pymc-devs <pymc.devs@gmail.com>
6
6
  License: .. _license:
@@ -1,10 +1,10 @@
1
1
  .. _extending_op_params:
2
2
 
3
- ===============
4
- Using Op params
5
- ===============
3
+ ================
4
+ Using COp params
5
+ ================
6
6
 
7
- The Op params is a facility to pass some runtime parameters to the
7
+ The COp params is a facility to pass some runtime parameters to the
8
8
  code of an op without modifying it. It can enable a single instance
9
9
  of C code to serve different needs and therefore reduce compilation.
10
10
 
@@ -53,7 +53,7 @@ following methods will be used for the type:
53
53
  - :meth:`__hash__ <Type.__hash__>`
54
54
  - :meth:`values_eq <Type.values_eq>`
55
55
 
56
- Additionally if you want to use your params with C code, you need to extend `COp`
56
+ Additionally, to use your params with C code, you need to extend `COp`
57
57
  and implement the following methods:
58
58
 
59
59
  - :meth:`c_declare <CLinkerType.c_declare>`
@@ -65,24 +65,24 @@ You can also define other convenience methods such as
65
65
  :meth:`c_headers <CLinkerType.c_headers>` if you need any special things.
66
66
 
67
67
 
68
- Registering the params with your Op
69
- -----------------------------------
68
+ Registering the params with your COp
69
+ ------------------------------------
70
70
 
71
- To declare that your Op uses params you have to set the class
71
+ To declare that your `COp` uses params you have to set the class
72
72
  attribute :attr:`params_type` to an instance of your params Type.
73
73
 
74
74
  .. note::
75
75
 
76
76
  If you want to have multiple parameters, PyTensor provides the convenient class
77
77
  :class:`pytensor.link.c.params_type.ParamsType` that allows to bundle many parameters into
78
- one object that will be available in both Python (as a Python object) and C code (as a struct).
78
+ one object that will be available to the C code (as a struct).
79
79
 
80
80
  For example if we decide to use an int as the params the following
81
81
  would be appropriate:
82
82
 
83
83
  .. code-block:: python
84
84
 
85
- class MyOp(Op):
85
+ class MyOp(COp):
86
86
  params_type = Generic()
87
87
 
88
88
  After that you need to define a :meth:`get_params` method on your
@@ -115,12 +115,7 @@ Having declared a params for your Op will affect the expected
115
115
  signature of :meth:`perform`. The new expected signature will have an
116
116
  extra parameter at the end which corresponds to the params object.
117
117
 
118
- .. warning::
119
-
120
- If you do not account for this extra parameter, the code will fail
121
- at runtime if it tries to run the python version.
122
-
123
- Also, for the C code, the `sub` dictionary will contain an extra entry
118
+ The `sub` dictionary for `COp`s with params will contain an extra entry
124
119
  `'params'` which will map to the variable name of the params object.
125
120
  This is true for all methods that receive a `sub` parameter, so this
126
121
  means that you can use your params in the :meth:`c_code <COp.c_code>`
@@ -131,7 +126,7 @@ A simple example
131
126
  ----------------
132
127
 
133
128
  This is a simple example which uses a params object to pass a value.
134
- This `Op` will multiply a scalar input by a fixed floating point value.
129
+ This `COp` will multiply a scalar input by a fixed floating point value.
135
130
 
136
131
  Since the value in this case is a python float, we chose Generic as
137
132
  the params type.
@@ -156,9 +151,10 @@ the params type.
156
151
  inp = as_scalar(inp)
157
152
  return Apply(self, [inp], [inp.type()])
158
153
 
159
- def perform(self, node, inputs, output_storage, params):
160
- # Here params is a python float so this is ok
161
- output_storage[0][0] = inputs[0] * params
154
+ def perform(self, node, inputs, output_storage):
155
+ # Because params is a python float we can use `self.mul` directly.
156
+ # If it's something fancier, call `self.params_type.filter(self.get_params(node))`
157
+ output_storage[0][0] = inputs[0] * self.mul
162
158
 
163
159
  def c_code(self, node, name, inputs, outputs, sub):
164
160
  return ("%(z)s = %(x)s * PyFloat_AsDouble(%(p)s);" %
@@ -174,7 +170,7 @@ weights.
174
170
 
175
171
  .. testcode::
176
172
 
177
- from pytensor.graph.op import Op
173
+ from pytensor.link.c.op import COp
178
174
  from pytensor.link.c.type import Generic
179
175
  from pytensor.scalar import as_scalar
180
176
 
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2023-11-20T14:04:50+0100",
11
+ "date": "2023-12-10T11:56:35+0000",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "eb552eef7a8381e47a38ce0694244700693cb978",
15
- "version": "2.18.0"
14
+ "full-revisionid": "68b41a480bc9fed69db7331f60543e94241adbd5",
15
+ "version": "2.18.2"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -1474,7 +1474,7 @@ class FunctionMaker:
1474
1474
  if getattr(mode, "profile", None):
1475
1475
  raise TypeError("profile passed via 'mode'. This isn't supported anymore")
1476
1476
  self.profile = profile
1477
- if profile:
1477
+ if profile and config.cxx:
1478
1478
  # This is very important:
1479
1479
  # 1) We preload the cache here to not have its timing
1480
1480
  # included with the rewrites.
@@ -1482,7 +1482,12 @@ class FunctionMaker:
1482
1482
  # too much execution time during testing as we compile
1483
1483
  # much more functions then the number of compile c
1484
1484
  # module.
1485
+ start_get_cache = time.perf_counter()
1485
1486
  pytensor.link.c.basic.get_module_cache().refresh()
1487
+ get_cache_time = time.perf_counter() - start_get_cache
1488
+ self.profile.linker_time += get_cache_time
1489
+ self.profile.preload_cache_time += get_cache_time
1490
+
1486
1491
  # Handle the case where inputs and/or outputs is a single
1487
1492
  # Variable (not in a list)
1488
1493
  unpack_single = False
@@ -1722,7 +1727,8 @@ def orig_function(
1722
1727
 
1723
1728
  """
1724
1729
 
1725
- t1 = time.perf_counter()
1730
+ if profile:
1731
+ t1 = time.perf_counter()
1726
1732
  mode = pytensor.compile.mode.get_mode(mode)
1727
1733
 
1728
1734
  inputs = list(map(convert_function_input, inputs))
@@ -1755,8 +1761,8 @@ def orig_function(
1755
1761
  with config.change_flags(compute_test_value="off"):
1756
1762
  fn = m.create(defaults)
1757
1763
  finally:
1758
- t2 = time.perf_counter()
1759
- if fn and profile:
1764
+ if profile and fn:
1765
+ t2 = time.perf_counter()
1760
1766
  profile.compile_time += t2 - t1
1761
1767
  # TODO: append
1762
1768
  profile.nb_nodes = len(fn.maker.fgraph.apply_nodes)
@@ -269,6 +269,9 @@ class ProfileStats:
269
269
  linker_time: float = 0.0
270
270
  # time spent linking graph (FunctionMaker.create)
271
271
 
272
+ preload_cache_time: float = 0.0
273
+ # time spent preloading the cache, so it does not affect rewrites profiling
274
+
272
275
  import_time: float = 0.0
273
276
  # time spent in importing compiled python module.
274
277
 
@@ -811,6 +814,7 @@ class ProfileStats:
811
814
  ),
812
815
  file=file,
813
816
  )
817
+ print(f" C-cache preloading {self.preload_cache_time:e}s", file=file)
814
818
  print(f" Import time {self.import_time:e}s", file=file)
815
819
  print(
816
820
  f" Node make_thunk time {self.linker_node_make_thunks:e}s", file=file
@@ -30,7 +30,6 @@ import numpy as np
30
30
  from pytensor.configdefaults import config
31
31
  from pytensor.graph.utils import (
32
32
  MetaObject,
33
- MethodNotDefined,
34
33
  Scratchpad,
35
34
  TestValueError,
36
35
  ValidatingScratchpad,
@@ -151,16 +150,6 @@ class Apply(Node, Generic[OpType]):
151
150
  f"The 'outputs' argument to Apply must contain Variable instances with no owner, not {output}"
152
151
  )
153
152
 
154
- def run_params(self):
155
- """
156
- Returns the params for the node, or NoParams if no params is set.
157
-
158
- """
159
- try:
160
- return self.op.get_params(self)
161
- except MethodNotDefined:
162
- return NoParams
163
-
164
153
  def __getstate__(self):
165
154
  d = self.__dict__
166
155
  # ufunc don't pickle/unpickle well
@@ -1788,6 +1777,7 @@ def equal_computations(
1788
1777
  ys: list[Union[np.ndarray, Variable]],
1789
1778
  in_xs: Optional[list[Variable]] = None,
1790
1779
  in_ys: Optional[list[Variable]] = None,
1780
+ strict_dtype=True,
1791
1781
  ) -> bool:
1792
1782
  """Checks if PyTensor graphs represent the same computations.
1793
1783
 
@@ -1919,7 +1909,10 @@ def equal_computations(
1919
1909
  if dx != dy:
1920
1910
  if isinstance(dx, Constant) and isinstance(dy, Constant):
1921
1911
  if not dx.equals(dy):
1922
- return False
1912
+ if strict_dtype:
1913
+ return False
1914
+ elif not np.array_equal(dx.data, dy.data):
1915
+ return False
1923
1916
  else:
1924
1917
  return False
1925
1918
 
@@ -16,15 +16,13 @@ from typing import (
16
16
 
17
17
  import pytensor
18
18
  from pytensor.configdefaults import config
19
- from pytensor.graph.basic import Apply, NoParams, Variable
19
+ from pytensor.graph.basic import Apply, Variable
20
20
  from pytensor.graph.utils import (
21
21
  MetaObject,
22
- MethodNotDefined,
23
22
  TestValueError,
24
23
  add_tag_trace,
25
24
  get_variable_trace_string,
26
25
  )
27
- from pytensor.link.c.params_type import Params, ParamsType
28
26
 
29
27
 
30
28
  if TYPE_CHECKING:
@@ -37,10 +35,7 @@ StorageMapType = dict[Variable, StorageCellType]
37
35
  ComputeMapType = dict[Variable, list[bool]]
38
36
  InputStorageType = list[StorageCellType]
39
37
  OutputStorageType = list[StorageCellType]
40
- ParamsInputType = Optional[tuple[Any, ...]]
41
- PerformMethodType = Callable[
42
- [Apply, list[Any], OutputStorageType, ParamsInputType], None
43
- ]
38
+ PerformMethodType = Callable[[Apply, list[Any], OutputStorageType], None]
44
39
  BasicThunkType = Callable[[], None]
45
40
  ThunkCallableType = Callable[
46
41
  [PerformMethodType, StorageMapType, ComputeMapType, Apply], None
@@ -202,7 +197,6 @@ class Op(MetaObject):
202
197
 
203
198
  itypes: Optional[Sequence["Type"]] = None
204
199
  otypes: Optional[Sequence["Type"]] = None
205
- params_type: Optional[ParamsType] = None
206
200
 
207
201
  _output_type_depends_on_input_value = False
208
202
  """
@@ -426,7 +420,6 @@ class Op(MetaObject):
426
420
  node: Apply,
427
421
  inputs: Sequence[Any],
428
422
  output_storage: OutputStorageType,
429
- params: ParamsInputType = None,
430
423
  ) -> None:
431
424
  """Calculate the function on the inputs and put the variables in the output storage.
432
425
 
@@ -442,8 +435,6 @@ class Op(MetaObject):
442
435
  these lists). Each sub-list corresponds to value of each
443
436
  `Variable` in :attr:`node.outputs`. The primary purpose of this method
444
437
  is to set the values of these sub-lists.
445
- params
446
- A tuple containing the values of each entry in :attr:`Op.__props__`.
447
438
 
448
439
  Notes
449
440
  -----
@@ -481,22 +472,6 @@ class Op(MetaObject):
481
472
  """
482
473
  return True
483
474
 
484
- def get_params(self, node: Apply) -> Params:
485
- """Try to get parameters for the `Op` when :attr:`Op.params_type` is set to a `ParamsType`."""
486
- if isinstance(self.params_type, ParamsType):
487
- wrapper = self.params_type
488
- if not all(hasattr(self, field) for field in wrapper.fields):
489
- # Let's print missing attributes for debugging.
490
- not_found = tuple(
491
- field for field in wrapper.fields if not hasattr(self, field)
492
- )
493
- raise AttributeError(
494
- f"{type(self).__name__}: missing attributes {not_found} for ParamsType."
495
- )
496
- # ParamsType.get_params() will apply filtering to attributes.
497
- return self.params_type.get_params(self)
498
- raise MethodNotDefined("get_params")
499
-
500
475
  def prepare_node(
501
476
  self,
502
477
  node: Apply,
@@ -538,34 +513,12 @@ class Op(MetaObject):
538
513
  else:
539
514
  p = node.op.perform
540
515
 
541
- params = node.run_params()
542
-
543
- if params is NoParams:
544
- # default arguments are stored in the closure of `rval`
545
- @is_thunk_type
546
- def rval(
547
- p=p, i=node_input_storage, o=node_output_storage, n=node, params=None
548
- ):
549
- r = p(n, [x[0] for x in i], o)
550
- for o in node.outputs:
551
- compute_map[o][0] = True
552
- return r
553
-
554
- else:
555
- params_val = node.params_type.filter(params)
556
-
557
- @is_thunk_type
558
- def rval(
559
- p=p,
560
- i=node_input_storage,
561
- o=node_output_storage,
562
- n=node,
563
- params=params_val,
564
- ):
565
- r = p(n, [x[0] for x in i], o, params)
566
- for o in node.outputs:
567
- compute_map[o][0] = True
568
- return r
516
+ @is_thunk_type
517
+ def rval(p=p, i=node_input_storage, o=node_output_storage, n=node):
518
+ r = p(n, [x[0] for x in i], o)
519
+ for o in node.outputs:
520
+ compute_map[o][0] = True
521
+ return r
569
522
 
570
523
  rval.inputs = node_input_storage
571
524
  rval.outputs = node_output_storage
@@ -640,7 +593,7 @@ class _NoPythonOp(Op):
640
593
 
641
594
  """
642
595
 
643
- def perform(self, node, inputs, output_storage, params=None):
596
+ def perform(self, node, inputs, output_storage):
644
597
  raise NotImplementedError("No Python implementation is provided by this Op.")
645
598
 
646
599
 
@@ -3,7 +3,13 @@ from collections.abc import Iterable, Mapping, Sequence
3
3
  from functools import partial, singledispatch
4
4
  from typing import Optional, Union, cast, overload
5
5
 
6
- from pytensor.graph.basic import Apply, Constant, Variable, truncated_graph_inputs
6
+ from pytensor.graph.basic import (
7
+ Apply,
8
+ Constant,
9
+ Variable,
10
+ io_toposort,
11
+ truncated_graph_inputs,
12
+ )
7
13
  from pytensor.graph.fg import FunctionGraph
8
14
  from pytensor.graph.op import Op
9
15
 
@@ -295,19 +301,14 @@ def vectorize_graph(
295
301
  inputs = truncated_graph_inputs(seq_outputs, ancestors_to_include=replace.keys())
296
302
  new_inputs = [replace.get(inp, inp) for inp in inputs]
297
303
 
298
- def transform(var: Variable) -> Variable:
299
- if var in inputs:
300
- return new_inputs[inputs.index(var)]
304
+ vect_vars = dict(zip(inputs, new_inputs))
305
+ for node in io_toposort(inputs, seq_outputs):
306
+ vect_inputs = [vect_vars.get(inp, inp) for inp in node.inputs]
307
+ vect_node = vectorize_node(node, *vect_inputs)
308
+ for output, vect_output in zip(node.outputs, vect_node.outputs):
309
+ vect_vars[output] = vect_output
301
310
 
302
- node = var.owner
303
- batched_inputs = [transform(inp) for inp in node.inputs]
304
- batched_node = vectorize_node(node, *batched_inputs)
305
- batched_var = batched_node.outputs[var.owner.outputs.index(var)]
306
-
307
- return cast(Variable, batched_var)
308
-
309
- # TODO: MergeOptimization or node caching?
310
- seq_vect_outputs = [transform(out) for out in seq_outputs]
311
+ seq_vect_outputs = [vect_vars[out] for out in seq_outputs]
311
312
 
312
313
  if isinstance(outputs, Sequence):
313
314
  return seq_vect_outputs
@@ -20,6 +20,7 @@ from pytensor.graph.basic import (
20
20
  io_toposort,
21
21
  vars_between,
22
22
  )
23
+ from pytensor.graph.utils import MethodNotDefined
23
24
  from pytensor.link.basic import Container, Linker, LocalLinker, PerformLinker
24
25
  from pytensor.link.c.cmodule import (
25
26
  METH_VARARGS,
@@ -617,7 +618,12 @@ class CLinker(Linker):
617
618
  # that needs it
618
619
  self.node_params = dict()
619
620
  for node in self.node_order:
620
- params = node.run_params()
621
+ if not isinstance(node.op, CLinkerOp):
622
+ continue
623
+ try:
624
+ params = node.op.get_params(node)
625
+ except MethodNotDefined:
626
+ params = NoParams
621
627
  if params is not NoParams:
622
628
  # try to avoid creating more than one variable for the
623
629
  # same params.
@@ -803,7 +809,10 @@ class CLinker(Linker):
803
809
 
804
810
  sub = dict(failure_var=failure_var)
805
811
 
806
- params = node.run_params()
812
+ try:
813
+ params = op.get_params(node)
814
+ except MethodNotDefined:
815
+ params = NoParams
807
816
  if params is not NoParams:
808
817
  params_var = symbol[self.node_params[params]]
809
818
 
@@ -2718,6 +2718,7 @@ def default_blas_ldflags():
2718
2718
  found = True
2719
2719
  break
2720
2720
  if not found:
2721
+ _logger.debug("Required file '%s' not found", req)
2721
2722
  raise RuntimeError(f"Required file {req} not found")
2722
2723
  return libs
2723
2724
 
@@ -2744,7 +2745,9 @@ def default_blas_ldflags():
2744
2745
  [pathlib.Path(p).resolve() for p in line[len("libraries: =") :].split(":")]
2745
2746
  for line in stdout.decode(sys.stdout.encoding).splitlines()
2746
2747
  if line.startswith("libraries: =")
2747
- ][0]
2748
+ ]
2749
+ if len(maybe_lib_dirs) > 0:
2750
+ maybe_lib_dirs = maybe_lib_dirs[0]
2748
2751
  return [str(d) for d in maybe_lib_dirs if d.exists() and d.is_dir()]
2749
2752
 
2750
2753
  def check_libs(
@@ -2777,9 +2780,15 @@ def default_blas_ldflags():
2777
2780
  res = try_blas_flag(flags)
2778
2781
  if res:
2779
2782
  if any("mkl" in flag for flag in flags):
2780
- check_mkl_openmp()
2783
+ try:
2784
+ check_mkl_openmp()
2785
+ except Exception as e:
2786
+ _logger.debug(e)
2787
+ _logger.debug("The following blas flags will be used: '%s'", res)
2781
2788
  return res
2782
2789
  else:
2790
+ _logger.debug(f"Supplied flags {res} failed to compile")
2791
+ _logger.debug("Supplied flags '%s' failed to compile", res)
2783
2792
  raise RuntimeError(f"Supplied flags {flags} failed to compile")
2784
2793
 
2785
2794
  # If no compiler is available we default to empty ldflags
@@ -2793,6 +2802,18 @@ def default_blas_ldflags():
2793
2802
 
2794
2803
  cxx_library_dirs = get_cxx_library_dirs()
2795
2804
  searched_library_dirs = cxx_library_dirs + _std_lib_dirs
2805
+ if sys.platform == "win32":
2806
+ # Conda on Windows saves MKL libraries under CONDA_PREFIX\Library\bin
2807
+ # From the conda manual (https://docs.conda.io/projects/conda-build/en/stable/user-guide/environment-variables.html)
2808
+ # it seems like conda could also save some libraries into the CONDA_PREFIX\Library\lib
2809
+ # directory. We will include both in our searched library dirs
2810
+ searched_library_dirs.append(os.path.join(sys.prefix, "Library", "bin"))
2811
+ searched_library_dirs.append(os.path.join(sys.prefix, "Library", "lib"))
2812
+ search_dirs = "\n".join(searched_library_dirs)
2813
+ _logger.debug(
2814
+ "Will search for BLAS libraries in the following directories:\n%s",
2815
+ search_dirs,
2816
+ )
2796
2817
  all_libs = [
2797
2818
  l
2798
2819
  for path in [
@@ -2808,6 +2829,7 @@ def default_blas_ldflags():
2808
2829
  maybe_add_to_os_environ_pathlist("PATH", rpath)
2809
2830
  try:
2810
2831
  # 1. Try to use MKL with INTEL OpenMP threading
2832
+ _logger.debug("Checking MKL flags with intel threading")
2811
2833
  return check_libs(
2812
2834
  all_libs,
2813
2835
  required_libs=[
@@ -2820,19 +2842,21 @@ def default_blas_ldflags():
2820
2842
  extra_compile_flags=[f"-Wl,-rpath,{rpath}"] if rpath is not None else [],
2821
2843
  cxx_library_dirs=cxx_library_dirs,
2822
2844
  )
2823
- except Exception:
2824
- pass
2845
+ except Exception as e:
2846
+ _logger.debug(e)
2825
2847
  try:
2826
2848
  # 2. Try to use MKL with GNU OpenMP threading
2849
+ _logger.debug("Checking MKL flags with GNU OpenMP threading")
2827
2850
  return check_libs(
2828
2851
  all_libs,
2829
2852
  required_libs=["mkl_core", "mkl_rt", "mkl_gnu_thread", "gomp", "pthread"],
2830
2853
  extra_compile_flags=[f"-Wl,-rpath,{rpath}"] if rpath is not None else [],
2831
2854
  cxx_library_dirs=cxx_library_dirs,
2832
2855
  )
2833
- except Exception:
2834
- pass
2856
+ except Exception as e:
2857
+ _logger.debug(e)
2835
2858
  try:
2859
+ _logger.debug("Checking Lapack + blas")
2836
2860
  # 3. Try to use LAPACK + BLAS
2837
2861
  return check_libs(
2838
2862
  all_libs,
@@ -2840,20 +2864,22 @@ def default_blas_ldflags():
2840
2864
  extra_compile_flags=[f"-Wl,-rpath,{rpath}"] if rpath is not None else [],
2841
2865
  cxx_library_dirs=cxx_library_dirs,
2842
2866
  )
2843
- except Exception:
2844
- pass
2867
+ except Exception as e:
2868
+ _logger.debug(e)
2845
2869
  try:
2846
2870
  # 4. Try to use BLAS alone
2871
+ _logger.debug("Checking blas alone")
2847
2872
  return check_libs(
2848
2873
  all_libs,
2849
2874
  required_libs=["blas", "cblas"],
2850
2875
  extra_compile_flags=[f"-Wl,-rpath,{rpath}"] if rpath is not None else [],
2851
2876
  cxx_library_dirs=cxx_library_dirs,
2852
2877
  )
2853
- except Exception:
2854
- pass
2878
+ except Exception as e:
2879
+ _logger.debug(e)
2855
2880
  try:
2856
2881
  # 5. Try to use openblas
2882
+ _logger.debug("Checking openblas")
2857
2883
  return check_libs(
2858
2884
  all_libs,
2859
2885
  required_libs=["openblas", "gfortran", "gomp", "m"],
@@ -2862,8 +2888,9 @@ def default_blas_ldflags():
2862
2888
  else ["-fopenmp"],
2863
2889
  cxx_library_dirs=cxx_library_dirs,
2864
2890
  )
2865
- except Exception:
2866
- pass
2891
+ except Exception as e:
2892
+ _logger.debug(e)
2893
+ _logger.debug("Failed to identify blas ldflags. Will leave them empty.")
2867
2894
  return ""
2868
2895
 
2869
2896
 
@@ -1,11 +1,16 @@
1
+ import typing
1
2
  import warnings
2
3
  from abc import abstractmethod
3
- from typing import Callable
4
+ from typing import Callable, Optional
4
5
 
5
6
  from pytensor.graph.basic import Apply, Constant
6
7
  from pytensor.graph.utils import MethodNotDefined
7
8
 
8
9
 
10
+ if typing.TYPE_CHECKING:
11
+ from pytensor.link.c.params_type import Params, ParamsType
12
+
13
+
9
14
  class CLinkerObject:
10
15
  """Standard methods for an `Op` or `Type` used with the `CLinker`."""
11
16
 
@@ -172,6 +177,8 @@ class CLinkerObject:
172
177
  class CLinkerOp(CLinkerObject):
173
178
  """Interface definition for `Op` subclasses compiled by `CLinker`."""
174
179
 
180
+ params_type: Optional["ParamsType"] = None
181
+
175
182
  @abstractmethod
176
183
  def c_code(
177
184
  self,
@@ -362,6 +369,22 @@ class CLinkerOp(CLinkerObject):
362
369
  """
363
370
  return ""
364
371
 
372
+ def get_params(self, node: Apply) -> "Params":
373
+ """Try to get parameters for the `Op` when :attr:`Op.params_type` is set to a `ParamsType`."""
374
+ if self.params_type is not None:
375
+ wrapper = self.params_type
376
+ if not all(hasattr(self, field) for field in wrapper.fields):
377
+ # Let's print missing attributes for debugging.
378
+ not_found = tuple(
379
+ field for field in wrapper.fields if not hasattr(self, field)
380
+ )
381
+ raise AttributeError(
382
+ f"{type(self).__name__}: missing attributes {not_found} for ParamsType."
383
+ )
384
+ # ParamsType.get_params() will apply filtering to attributes.
385
+ return self.params_type.get_params(self)
386
+ raise MethodNotDefined("get_params")
387
+
365
388
 
366
389
  class CLinkerType(CLinkerObject):
367
390
  r"""Interface specification for `Type`\s that can be arguments to a `CLinkerOp`.
@@ -664,7 +664,7 @@ class _NoPythonCOp(COp):
664
664
 
665
665
  """
666
666
 
667
- def perform(self, node, inputs, output_storage, params=None):
667
+ def perform(self, node, inputs, output_storage):
668
668
  raise NotImplementedError("No Python implementation is provided by this COp.")
669
669
 
670
670
 
@@ -675,7 +675,7 @@ class _NoPythonExternalCOp(ExternalCOp):
675
675
 
676
676
  """
677
677
 
678
- def perform(self, node, inputs, output_storage, params=None):
678
+ def perform(self, node, inputs, output_storage):
679
679
  raise NotImplementedError(
680
680
  "No Python implementation is provided by this ExternalCOp."
681
681
  )
@@ -99,9 +99,7 @@ def jax_funcify_BatchedDot(op, **kwargs):
99
99
  def batched_dot(a, b):
100
100
  if a.shape[0] != b.shape[0]:
101
101
  raise TypeError("Shapes must match in the 0-th dimension")
102
- if a.ndim == 2 or b.ndim == 2:
103
- return jnp.einsum("n...j,nj...->n...", a, b)
104
- return jnp.einsum("nij,njk->nik", a, b)
102
+ return jnp.matmul(a, b)
105
103
 
106
104
  return batched_dot
107
105