ctpbee-opt-api 0.1.0__cp310-cp310-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 (414) hide show
  1. ctpbee_api/__init__.py +17 -0
  2. ctpbee_api/ctp/__init__.py +3 -0
  3. ctpbee_api/ctp/ctp_constant.py +1253 -0
  4. ctpbee_api/ctp/generator/concat.py +93 -0
  5. ctpbee_api/ctp/generator/const.py +325 -0
  6. ctpbee_api/ctp/generator/ctp_constant.py +1274 -0
  7. ctpbee_api/ctp/generator/ctp_md_header_define.h +13 -0
  8. ctpbee_api/ctp/generator/ctp_md_header_function.h +6 -0
  9. ctpbee_api/ctp/generator/ctp_md_header_on.h +26 -0
  10. ctpbee_api/ctp/generator/ctp_md_header_process.h +26 -0
  11. ctpbee_api/ctp/generator/ctp_md_source_function.cpp +42 -0
  12. ctpbee_api/ctp/generator/ctp_md_source_module.cpp +18 -0
  13. ctpbee_api/ctp/generator/ctp_md_source_on.cpp +156 -0
  14. ctpbee_api/ctp/generator/ctp_md_source_process.cpp +282 -0
  15. ctpbee_api/ctp/generator/ctp_md_source_switch.cpp +78 -0
  16. ctpbee_api/ctp/generator/ctp_md_source_task.cpp +211 -0
  17. ctpbee_api/ctp/generator/ctp_struct.py +5640 -0
  18. ctpbee_api/ctp/generator/ctp_td_header_define.h +130 -0
  19. ctpbee_api/ctp/generator/ctp_td_header_function.h +174 -0
  20. ctpbee_api/ctp/generator/ctp_td_header_on.h +260 -0
  21. ctpbee_api/ctp/generator/ctp_td_header_process.h +260 -0
  22. ctpbee_api/ctp/generator/ctp_td_source_function.cpp +1456 -0
  23. ctpbee_api/ctp/generator/ctp_td_source_module.cpp +222 -0
  24. ctpbee_api/ctp/generator/ctp_td_source_on.cpp +1572 -0
  25. ctpbee_api/ctp/generator/ctp_td_source_process.cpp +5472 -0
  26. ctpbee_api/ctp/generator/ctp_td_source_switch.cpp +780 -0
  27. ctpbee_api/ctp/generator/ctp_td_source_task.cpp +2444 -0
  28. ctpbee_api/ctp/generator/ctp_typedef.py +800 -0
  29. ctpbee_api/ctp/generator/generate_api_functions.py +345 -0
  30. ctpbee_api/ctp/generator/generate_data_type.py +76 -0
  31. ctpbee_api/ctp/generator/generate_struct.py +84 -0
  32. ctpbee_api/ctp/include/mac/ctp/ThostFtdcMdApi.h +168 -0
  33. ctpbee_api/ctp/include/mac/ctp/ThostFtdcTraderApi.h +770 -0
  34. ctpbee_api/ctp/include/mac/ctp/ThostFtdcUserApiDataType.h +6878 -0
  35. ctpbee_api/ctp/include/mac/ctp/ThostFtdcUserApiStruct.h +10915 -0
  36. ctpbee_api/ctp/include/mac/pybind11/attr.h +690 -0
  37. ctpbee_api/ctp/include/mac/pybind11/buffer_info.h +208 -0
  38. ctpbee_api/ctp/include/mac/pybind11/cast.h +1704 -0
  39. ctpbee_api/ctp/include/mac/pybind11/chrono.h +225 -0
  40. ctpbee_api/ctp/include/mac/pybind11/common.h +2 -0
  41. ctpbee_api/ctp/include/mac/pybind11/complex.h +74 -0
  42. ctpbee_api/ctp/include/mac/pybind11/detail/class.h +743 -0
  43. ctpbee_api/ctp/include/mac/pybind11/detail/common.h +1255 -0
  44. ctpbee_api/ctp/include/mac/pybind11/detail/descr.h +171 -0
  45. ctpbee_api/ctp/include/mac/pybind11/detail/init.h +434 -0
  46. ctpbee_api/ctp/include/mac/pybind11/detail/internals.h +656 -0
  47. ctpbee_api/ctp/include/mac/pybind11/detail/type_caster_base.h +1177 -0
  48. ctpbee_api/ctp/include/mac/pybind11/detail/typeid.h +65 -0
  49. ctpbee_api/ctp/include/mac/pybind11/eigen/common.h +9 -0
  50. ctpbee_api/ctp/include/mac/pybind11/eigen/matrix.h +714 -0
  51. ctpbee_api/ctp/include/mac/pybind11/eigen/tensor.h +516 -0
  52. ctpbee_api/ctp/include/mac/pybind11/eigen.h +12 -0
  53. ctpbee_api/ctp/include/mac/pybind11/embed.h +316 -0
  54. ctpbee_api/ctp/include/mac/pybind11/eval.h +156 -0
  55. ctpbee_api/ctp/include/mac/pybind11/functional.h +137 -0
  56. ctpbee_api/ctp/include/mac/pybind11/gil.h +239 -0
  57. ctpbee_api/ctp/include/mac/pybind11/iostream.h +265 -0
  58. ctpbee_api/ctp/include/mac/pybind11/numpy.h +1998 -0
  59. ctpbee_api/ctp/include/mac/pybind11/operators.h +202 -0
  60. ctpbee_api/ctp/include/mac/pybind11/options.h +92 -0
  61. ctpbee_api/ctp/include/mac/pybind11/pybind11.h +2890 -0
  62. ctpbee_api/ctp/include/mac/pybind11/pytypes.h +2557 -0
  63. ctpbee_api/ctp/include/mac/pybind11/stl/filesystem.h +116 -0
  64. ctpbee_api/ctp/include/mac/pybind11/stl.h +447 -0
  65. ctpbee_api/ctp/include/mac/pybind11/stl_bind.h +851 -0
  66. ctpbee_api/ctp/include/mac/pybind11/type_caster_pyobject_ptr.h +61 -0
  67. ctpbee_api/ctp/include/new/ctp/ThostFtdcMdApi.h +168 -0
  68. ctpbee_api/ctp/include/new/ctp/ThostFtdcTraderApi.h +770 -0
  69. ctpbee_api/ctp/include/new/ctp/ThostFtdcUserApiDataType.h +6878 -0
  70. ctpbee_api/ctp/include/new/ctp/ThostFtdcUserApiStruct.h +10915 -0
  71. ctpbee_api/ctp/include/new/pybind11/attr.h +690 -0
  72. ctpbee_api/ctp/include/new/pybind11/buffer_info.h +208 -0
  73. ctpbee_api/ctp/include/new/pybind11/cast.h +1704 -0
  74. ctpbee_api/ctp/include/new/pybind11/chrono.h +225 -0
  75. ctpbee_api/ctp/include/new/pybind11/common.h +2 -0
  76. ctpbee_api/ctp/include/new/pybind11/complex.h +74 -0
  77. ctpbee_api/ctp/include/new/pybind11/detail/class.h +743 -0
  78. ctpbee_api/ctp/include/new/pybind11/detail/common.h +1255 -0
  79. ctpbee_api/ctp/include/new/pybind11/detail/descr.h +171 -0
  80. ctpbee_api/ctp/include/new/pybind11/detail/init.h +434 -0
  81. ctpbee_api/ctp/include/new/pybind11/detail/internals.h +656 -0
  82. ctpbee_api/ctp/include/new/pybind11/detail/type_caster_base.h +1177 -0
  83. ctpbee_api/ctp/include/new/pybind11/detail/typeid.h +65 -0
  84. ctpbee_api/ctp/include/new/pybind11/eigen/common.h +9 -0
  85. ctpbee_api/ctp/include/new/pybind11/eigen/matrix.h +714 -0
  86. ctpbee_api/ctp/include/new/pybind11/eigen/tensor.h +516 -0
  87. ctpbee_api/ctp/include/new/pybind11/eigen.h +12 -0
  88. ctpbee_api/ctp/include/new/pybind11/embed.h +316 -0
  89. ctpbee_api/ctp/include/new/pybind11/eval.h +156 -0
  90. ctpbee_api/ctp/include/new/pybind11/functional.h +137 -0
  91. ctpbee_api/ctp/include/new/pybind11/gil.h +239 -0
  92. ctpbee_api/ctp/include/new/pybind11/iostream.h +265 -0
  93. ctpbee_api/ctp/include/new/pybind11/numpy.h +1998 -0
  94. ctpbee_api/ctp/include/new/pybind11/operators.h +202 -0
  95. ctpbee_api/ctp/include/new/pybind11/options.h +92 -0
  96. ctpbee_api/ctp/include/new/pybind11/pybind11.h +2890 -0
  97. ctpbee_api/ctp/include/new/pybind11/pytypes.h +2557 -0
  98. ctpbee_api/ctp/include/new/pybind11/stl/filesystem.h +116 -0
  99. ctpbee_api/ctp/include/new/pybind11/stl.h +447 -0
  100. ctpbee_api/ctp/include/new/pybind11/stl_bind.h +851 -0
  101. ctpbee_api/ctp/include/new/pybind11/type_caster_pyobject_ptr.h +61 -0
  102. ctpbee_api/ctp/include/previous/ctp/ThostFtdcMdApi.h +168 -0
  103. ctpbee_api/ctp/include/previous/ctp/ThostFtdcTraderApi.h +770 -0
  104. ctpbee_api/ctp/include/previous/ctp/ThostFtdcUserApiDataType.h +6878 -0
  105. ctpbee_api/ctp/include/previous/ctp/ThostFtdcUserApiStruct.h +10915 -0
  106. ctpbee_api/ctp/include/previous/pybind11/attr.h +489 -0
  107. ctpbee_api/ctp/include/previous/pybind11/buffer_info.h +108 -0
  108. ctpbee_api/ctp/include/previous/pybind11/cast.h +2067 -0
  109. ctpbee_api/ctp/include/previous/pybind11/chrono.h +162 -0
  110. ctpbee_api/ctp/include/previous/pybind11/common.h +2 -0
  111. ctpbee_api/ctp/include/previous/pybind11/complex.h +61 -0
  112. ctpbee_api/ctp/include/previous/pybind11/detail/class.h +626 -0
  113. ctpbee_api/ctp/include/previous/pybind11/detail/common.h +803 -0
  114. ctpbee_api/ctp/include/previous/pybind11/detail/descr.h +185 -0
  115. ctpbee_api/ctp/include/previous/pybind11/detail/init.h +335 -0
  116. ctpbee_api/ctp/include/previous/pybind11/detail/internals.h +285 -0
  117. ctpbee_api/ctp/include/previous/pybind11/detail/typeid.h +53 -0
  118. ctpbee_api/ctp/include/previous/pybind11/eigen.h +604 -0
  119. ctpbee_api/ctp/include/previous/pybind11/embed.h +194 -0
  120. ctpbee_api/ctp/include/previous/pybind11/eval.h +117 -0
  121. ctpbee_api/ctp/include/previous/pybind11/functional.h +85 -0
  122. ctpbee_api/ctp/include/previous/pybind11/iostream.h +200 -0
  123. ctpbee_api/ctp/include/previous/pybind11/numpy.h +1601 -0
  124. ctpbee_api/ctp/include/previous/pybind11/operators.h +168 -0
  125. ctpbee_api/ctp/include/previous/pybind11/options.h +65 -0
  126. ctpbee_api/ctp/include/previous/pybind11/pybind11.h +1965 -0
  127. ctpbee_api/ctp/include/previous/pybind11/pytypes.h +1332 -0
  128. ctpbee_api/ctp/include/previous/pybind11/stl.h +376 -0
  129. ctpbee_api/ctp/include/previous/pybind11/stl_bind.h +599 -0
  130. ctpbee_api/ctp/libs/libcomunicationkey.a +0 -0
  131. ctpbee_api/ctp/libs/libcrypto.a +0 -0
  132. ctpbee_api/ctp/libs/libssl.a +0 -0
  133. ctpbee_api/ctp/libs/thostmduserapi_se.lib +0 -0
  134. ctpbee_api/ctp/libs/thosttraderapi_se.lib +0 -0
  135. ctpbee_api/ctp/libthostmduserapi_se.so +0 -0
  136. ctpbee_api/ctp/libthosttraderapi_se.so +0 -0
  137. ctpbee_api/ctp/thostmduserapi_se.dll +0 -0
  138. ctpbee_api/ctp/thosttraderapi_se.dll +0 -0
  139. ctpbee_api/ctp/vnctp/vnctp.h +189 -0
  140. ctpbee_api/ctp/vnctp/vnctp.sln +41 -0
  141. ctpbee_api/ctp/vnctp/vnctpmd/dllmain.cpp +19 -0
  142. ctpbee_api/ctp/vnctp/vnctpmd/stdafx.cpp +1 -0
  143. ctpbee_api/ctp/vnctp/vnctpmd/stdafx.h +17 -0
  144. ctpbee_api/ctp/vnctp/vnctpmd/targetver.h +8 -0
  145. ctpbee_api/ctp/vnctp/vnctpmd/vnctpmd.cpp +953 -0
  146. ctpbee_api/ctp/vnctp/vnctpmd/vnctpmd.h +209 -0
  147. ctpbee_api/ctp/vnctp/vnctpmd/vnctpmd.vcxproj +200 -0
  148. ctpbee_api/ctp/vnctp/vnctpmd/vnctpmd.vcxproj.filters +54 -0
  149. ctpbee_api/ctp/vnctp/vnctpmd/vnctpmd.vcxproj.user +4 -0
  150. ctpbee_api/ctp/vnctp/vnctptd/dllmain.cpp +19 -0
  151. ctpbee_api/ctp/vnctp/vnctptd/stdafx.cpp +1 -0
  152. ctpbee_api/ctp/vnctp/vnctptd/stdafx.h +16 -0
  153. ctpbee_api/ctp/vnctp/vnctptd/targetver.h +8 -0
  154. ctpbee_api/ctp/vnctp/vnctptd/vnctptd.cpp +12148 -0
  155. ctpbee_api/ctp/vnctp/vnctptd/vnctptd.h +1329 -0
  156. ctpbee_api/ctp/vnctp/vnctptd/vnctptd.vcxproj +198 -0
  157. ctpbee_api/ctp/vnctp/vnctptd/vnctptd.vcxproj.filters +54 -0
  158. ctpbee_api/ctp/vnctp/vnctptd/vnctptd.vcxproj.user +4 -0
  159. ctpbee_api/ctp/vnctpmd.cp310-win_amd64.pyd +0 -0
  160. ctpbee_api/ctp/vnctptd.cp310-win_amd64.pyd +0 -0
  161. ctpbee_api/ctp_mini/__init__.py +3 -0
  162. ctpbee_api/ctp_mini/generator/generate_api_functions.py +343 -0
  163. ctpbee_api/ctp_mini/generator/generate_data_type.py +76 -0
  164. ctpbee_api/ctp_mini/generator/generate_struct.py +85 -0
  165. ctpbee_api/ctp_mini/generator/mini_constant.py +1186 -0
  166. ctpbee_api/ctp_mini/generator/mini_md_header_define.h +13 -0
  167. ctpbee_api/ctp_mini/generator/mini_md_header_function.h +4 -0
  168. ctpbee_api/ctp_mini/generator/mini_md_header_on.h +26 -0
  169. ctpbee_api/ctp_mini/generator/mini_md_header_process.h +26 -0
  170. ctpbee_api/ctp_mini/generator/mini_md_source_function.cpp +29 -0
  171. ctpbee_api/ctp_mini/generator/mini_md_source_module.cpp +17 -0
  172. ctpbee_api/ctp_mini/generator/mini_md_source_on.cpp +156 -0
  173. ctpbee_api/ctp_mini/generator/mini_md_source_process.cpp +264 -0
  174. ctpbee_api/ctp_mini/generator/mini_md_source_switch.cpp +78 -0
  175. ctpbee_api/ctp_mini/generator/mini_md_source_task.cpp +203 -0
  176. ctpbee_api/ctp_mini/generator/mini_struct.py +4599 -0
  177. ctpbee_api/ctp_mini/generator/mini_td_header_define.h +63 -0
  178. ctpbee_api/ctp_mini/generator/mini_td_header_function.h +84 -0
  179. ctpbee_api/ctp_mini/generator/mini_td_header_on.h +126 -0
  180. ctpbee_api/ctp_mini/generator/mini_td_header_process.h +126 -0
  181. ctpbee_api/ctp_mini/generator/mini_td_source_function.cpp +663 -0
  182. ctpbee_api/ctp_mini/generator/mini_td_source_module.cpp +107 -0
  183. ctpbee_api/ctp_mini/generator/mini_td_source_on.cpp +756 -0
  184. ctpbee_api/ctp_mini/generator/mini_td_source_process.cpp +2492 -0
  185. ctpbee_api/ctp_mini/generator/mini_td_source_switch.cpp +378 -0
  186. ctpbee_api/ctp_mini/generator/mini_td_source_task.cpp +1193 -0
  187. ctpbee_api/ctp_mini/generator/mini_typedef.py +755 -0
  188. ctpbee_api/ctp_mini/generator/package/vnminimd.cpp +886 -0
  189. ctpbee_api/ctp_mini/generator/package/vnminimd.h +205 -0
  190. ctpbee_api/ctp_mini/include/new/mini/ThostFtdcMdApi.h +148 -0
  191. ctpbee_api/ctp_mini/include/new/mini/ThostFtdcTraderApi.h +419 -0
  192. ctpbee_api/ctp_mini/include/new/mini/ThostFtdcUserApiDataType.h +6458 -0
  193. ctpbee_api/ctp_mini/include/new/mini/ThostFtdcUserApiStruct.h +8890 -0
  194. ctpbee_api/ctp_mini/include/new/pybind11/attr.h +690 -0
  195. ctpbee_api/ctp_mini/include/new/pybind11/buffer_info.h +208 -0
  196. ctpbee_api/ctp_mini/include/new/pybind11/cast.h +1704 -0
  197. ctpbee_api/ctp_mini/include/new/pybind11/chrono.h +225 -0
  198. ctpbee_api/ctp_mini/include/new/pybind11/common.h +2 -0
  199. ctpbee_api/ctp_mini/include/new/pybind11/complex.h +74 -0
  200. ctpbee_api/ctp_mini/include/new/pybind11/detail/class.h +743 -0
  201. ctpbee_api/ctp_mini/include/new/pybind11/detail/common.h +1255 -0
  202. ctpbee_api/ctp_mini/include/new/pybind11/detail/descr.h +171 -0
  203. ctpbee_api/ctp_mini/include/new/pybind11/detail/init.h +434 -0
  204. ctpbee_api/ctp_mini/include/new/pybind11/detail/internals.h +656 -0
  205. ctpbee_api/ctp_mini/include/new/pybind11/detail/type_caster_base.h +1177 -0
  206. ctpbee_api/ctp_mini/include/new/pybind11/detail/typeid.h +65 -0
  207. ctpbee_api/ctp_mini/include/new/pybind11/eigen/common.h +9 -0
  208. ctpbee_api/ctp_mini/include/new/pybind11/eigen/matrix.h +714 -0
  209. ctpbee_api/ctp_mini/include/new/pybind11/eigen/tensor.h +516 -0
  210. ctpbee_api/ctp_mini/include/new/pybind11/eigen.h +12 -0
  211. ctpbee_api/ctp_mini/include/new/pybind11/embed.h +316 -0
  212. ctpbee_api/ctp_mini/include/new/pybind11/eval.h +156 -0
  213. ctpbee_api/ctp_mini/include/new/pybind11/functional.h +137 -0
  214. ctpbee_api/ctp_mini/include/new/pybind11/gil.h +239 -0
  215. ctpbee_api/ctp_mini/include/new/pybind11/iostream.h +265 -0
  216. ctpbee_api/ctp_mini/include/new/pybind11/numpy.h +1998 -0
  217. ctpbee_api/ctp_mini/include/new/pybind11/operators.h +202 -0
  218. ctpbee_api/ctp_mini/include/new/pybind11/options.h +92 -0
  219. ctpbee_api/ctp_mini/include/new/pybind11/pybind11.h +2890 -0
  220. ctpbee_api/ctp_mini/include/new/pybind11/pytypes.h +2557 -0
  221. ctpbee_api/ctp_mini/include/new/pybind11/stl/filesystem.h +116 -0
  222. ctpbee_api/ctp_mini/include/new/pybind11/stl.h +447 -0
  223. ctpbee_api/ctp_mini/include/new/pybind11/stl_bind.h +851 -0
  224. ctpbee_api/ctp_mini/include/new/pybind11/type_caster_pyobject_ptr.h +61 -0
  225. ctpbee_api/ctp_mini/include/previous/mini/ThostFtdcMdApi.h +148 -0
  226. ctpbee_api/ctp_mini/include/previous/mini/ThostFtdcTraderApi.h +419 -0
  227. ctpbee_api/ctp_mini/include/previous/mini/ThostFtdcUserApiDataType.h +6458 -0
  228. ctpbee_api/ctp_mini/include/previous/mini/ThostFtdcUserApiStruct.h +8890 -0
  229. ctpbee_api/ctp_mini/include/previous/pybind11/attr.h +489 -0
  230. ctpbee_api/ctp_mini/include/previous/pybind11/buffer_info.h +108 -0
  231. ctpbee_api/ctp_mini/include/previous/pybind11/cast.h +2067 -0
  232. ctpbee_api/ctp_mini/include/previous/pybind11/chrono.h +162 -0
  233. ctpbee_api/ctp_mini/include/previous/pybind11/common.h +2 -0
  234. ctpbee_api/ctp_mini/include/previous/pybind11/complex.h +61 -0
  235. ctpbee_api/ctp_mini/include/previous/pybind11/detail/class.h +626 -0
  236. ctpbee_api/ctp_mini/include/previous/pybind11/detail/common.h +803 -0
  237. ctpbee_api/ctp_mini/include/previous/pybind11/detail/descr.h +185 -0
  238. ctpbee_api/ctp_mini/include/previous/pybind11/detail/init.h +335 -0
  239. ctpbee_api/ctp_mini/include/previous/pybind11/detail/internals.h +285 -0
  240. ctpbee_api/ctp_mini/include/previous/pybind11/detail/typeid.h +53 -0
  241. ctpbee_api/ctp_mini/include/previous/pybind11/eigen.h +604 -0
  242. ctpbee_api/ctp_mini/include/previous/pybind11/embed.h +194 -0
  243. ctpbee_api/ctp_mini/include/previous/pybind11/eval.h +117 -0
  244. ctpbee_api/ctp_mini/include/previous/pybind11/functional.h +85 -0
  245. ctpbee_api/ctp_mini/include/previous/pybind11/iostream.h +200 -0
  246. ctpbee_api/ctp_mini/include/previous/pybind11/numpy.h +1601 -0
  247. ctpbee_api/ctp_mini/include/previous/pybind11/operators.h +168 -0
  248. ctpbee_api/ctp_mini/include/previous/pybind11/options.h +65 -0
  249. ctpbee_api/ctp_mini/include/previous/pybind11/pybind11.h +1965 -0
  250. ctpbee_api/ctp_mini/include/previous/pybind11/pytypes.h +1332 -0
  251. ctpbee_api/ctp_mini/include/previous/pybind11/stl.h +376 -0
  252. ctpbee_api/ctp_mini/include/previous/pybind11/stl_bind.h +599 -0
  253. ctpbee_api/ctp_mini/libs/thostmduserapi.lib +0 -0
  254. ctpbee_api/ctp_mini/libs/thosttraderapi.lib +0 -0
  255. ctpbee_api/ctp_mini/libthostmduserapi.so +0 -0
  256. ctpbee_api/ctp_mini/libthosttraderapi.so +0 -0
  257. ctpbee_api/ctp_mini/mini_constant.py +1186 -0
  258. ctpbee_api/ctp_mini/thostmduserapi.dll +0 -0
  259. ctpbee_api/ctp_mini/thosttraderapi.dll +0 -0
  260. ctpbee_api/ctp_mini/vnctp_mini/vnctp_mini.h +146 -0
  261. ctpbee_api/ctp_mini/vnctp_mini/vnctp_mini.sln +41 -0
  262. ctpbee_api/ctp_mini/vnctp_mini/vnctp_minimd/dllmain.cpp +0 -0
  263. ctpbee_api/ctp_mini/vnctp_mini/vnctp_minimd/stdafx.cpp +0 -0
  264. ctpbee_api/ctp_mini/vnctp_mini/vnctp_minimd/stdafx.h +0 -0
  265. ctpbee_api/ctp_mini/vnctp_mini/vnctp_minimd/targetver.h +0 -0
  266. ctpbee_api/ctp_mini/vnctp_mini/vnctp_minimd/vnctp_minimd.cpp +886 -0
  267. ctpbee_api/ctp_mini/vnctp_mini/vnctp_minimd/vnctp_minimd.h +203 -0
  268. ctpbee_api/ctp_mini/vnctp_mini/vnctp_minimd/vnctp_minimd.vcxproj +183 -0
  269. ctpbee_api/ctp_mini/vnctp_mini/vnctp_minimd/vnctp_minimd.vcxproj.filters +54 -0
  270. ctpbee_api/ctp_mini/vnctp_mini/vnctp_minimd/vnctp_minimd.vcxproj.user +4 -0
  271. ctpbee_api/ctp_mini/vnctp_mini/vnctp_minitd/dllmain.cpp +0 -0
  272. ctpbee_api/ctp_mini/vnctp_mini/vnctp_minitd/stdafx.cpp +0 -0
  273. ctpbee_api/ctp_mini/vnctp_mini/vnctp_minitd/stdafx.h +0 -0
  274. ctpbee_api/ctp_mini/vnctp_mini/vnctp_minitd/targetver.h +0 -0
  275. ctpbee_api/ctp_mini/vnctp_mini/vnctp_minitd/vnctp_minitd.cpp +5716 -0
  276. ctpbee_api/ctp_mini/vnctp_mini/vnctp_minitd/vnctp_minitd.h +680 -0
  277. ctpbee_api/ctp_mini/vnctp_mini/vnctp_minitd/vnctp_minitd.vcxproj +180 -0
  278. ctpbee_api/ctp_mini/vnctp_mini/vnctp_minitd/vnctp_minitd.vcxproj.filters +54 -0
  279. ctpbee_api/ctp_mini/vnctp_mini/vnctp_minitd/vnctp_minitd.vcxproj.user +4 -0
  280. ctpbee_api/ctp_mini/vnctp_minimd.cp310-win_amd64.pyd +0 -0
  281. ctpbee_api/ctp_mini/vnctp_minitd.cp310-win_amd64.pyd +0 -0
  282. ctpbee_api/ctp_mini/vnctp_minitd.lib +0 -0
  283. ctpbee_api/rohon/RohonBaseV64.dll +0 -0
  284. ctpbee_api/rohon/WinDataCollect.dll +0 -0
  285. ctpbee_api/rohon/__init__.py +3 -0
  286. ctpbee_api/rohon/generator/generate_api_functions.py +348 -0
  287. ctpbee_api/rohon/generator/generate_data_type.py +76 -0
  288. ctpbee_api/rohon/generator/generate_struct.py +84 -0
  289. ctpbee_api/rohon/generator/rohon_constant.py +1242 -0
  290. ctpbee_api/rohon/generator/rohon_md_header_define.h +13 -0
  291. ctpbee_api/rohon/generator/rohon_md_header_function.h +6 -0
  292. ctpbee_api/rohon/generator/rohon_md_header_on.h +26 -0
  293. ctpbee_api/rohon/generator/rohon_md_header_process.h +26 -0
  294. ctpbee_api/rohon/generator/rohon_md_source_function.cpp +40 -0
  295. ctpbee_api/rohon/generator/rohon_md_source_module.cpp +18 -0
  296. ctpbee_api/rohon/generator/rohon_md_source_on.cpp +156 -0
  297. ctpbee_api/rohon/generator/rohon_md_source_process.cpp +271 -0
  298. ctpbee_api/rohon/generator/rohon_md_source_switch.cpp +78 -0
  299. ctpbee_api/rohon/generator/rohon_md_source_task.cpp +211 -0
  300. ctpbee_api/rohon/generator/rohon_struct.py +4958 -0
  301. ctpbee_api/rohon/generator/rohon_td_header_define.h +125 -0
  302. ctpbee_api/rohon/generator/rohon_td_header_function.h +164 -0
  303. ctpbee_api/rohon/generator/rohon_td_header_on.h +250 -0
  304. ctpbee_api/rohon/generator/rohon_td_header_process.h +250 -0
  305. ctpbee_api/rohon/generator/rohon_td_source_function.cpp +1338 -0
  306. ctpbee_api/rohon/generator/rohon_td_source_module.cpp +209 -0
  307. ctpbee_api/rohon/generator/rohon_td_source_on.cpp +1500 -0
  308. ctpbee_api/rohon/generator/rohon_td_source_process.cpp +5125 -0
  309. ctpbee_api/rohon/generator/rohon_td_source_switch.cpp +750 -0
  310. ctpbee_api/rohon/generator/rohon_td_source_task.cpp +2339 -0
  311. ctpbee_api/rohon/generator/rohon_typedef.py +781 -0
  312. ctpbee_api/rohon/include/new/pybind11/attr.h +690 -0
  313. ctpbee_api/rohon/include/new/pybind11/buffer_info.h +208 -0
  314. ctpbee_api/rohon/include/new/pybind11/cast.h +1704 -0
  315. ctpbee_api/rohon/include/new/pybind11/chrono.h +225 -0
  316. ctpbee_api/rohon/include/new/pybind11/common.h +2 -0
  317. ctpbee_api/rohon/include/new/pybind11/complex.h +74 -0
  318. ctpbee_api/rohon/include/new/pybind11/detail/class.h +743 -0
  319. ctpbee_api/rohon/include/new/pybind11/detail/common.h +1255 -0
  320. ctpbee_api/rohon/include/new/pybind11/detail/descr.h +171 -0
  321. ctpbee_api/rohon/include/new/pybind11/detail/init.h +434 -0
  322. ctpbee_api/rohon/include/new/pybind11/detail/internals.h +656 -0
  323. ctpbee_api/rohon/include/new/pybind11/detail/type_caster_base.h +1177 -0
  324. ctpbee_api/rohon/include/new/pybind11/detail/typeid.h +65 -0
  325. ctpbee_api/rohon/include/new/pybind11/eigen/common.h +9 -0
  326. ctpbee_api/rohon/include/new/pybind11/eigen/matrix.h +714 -0
  327. ctpbee_api/rohon/include/new/pybind11/eigen/tensor.h +516 -0
  328. ctpbee_api/rohon/include/new/pybind11/eigen.h +12 -0
  329. ctpbee_api/rohon/include/new/pybind11/embed.h +316 -0
  330. ctpbee_api/rohon/include/new/pybind11/eval.h +156 -0
  331. ctpbee_api/rohon/include/new/pybind11/functional.h +137 -0
  332. ctpbee_api/rohon/include/new/pybind11/gil.h +239 -0
  333. ctpbee_api/rohon/include/new/pybind11/iostream.h +265 -0
  334. ctpbee_api/rohon/include/new/pybind11/numpy.h +1998 -0
  335. ctpbee_api/rohon/include/new/pybind11/operators.h +202 -0
  336. ctpbee_api/rohon/include/new/pybind11/options.h +92 -0
  337. ctpbee_api/rohon/include/new/pybind11/pybind11.h +2890 -0
  338. ctpbee_api/rohon/include/new/pybind11/pytypes.h +2557 -0
  339. ctpbee_api/rohon/include/new/pybind11/stl/filesystem.h +116 -0
  340. ctpbee_api/rohon/include/new/pybind11/stl.h +447 -0
  341. ctpbee_api/rohon/include/new/pybind11/stl_bind.h +851 -0
  342. ctpbee_api/rohon/include/new/pybind11/type_caster_pyobject_ptr.h +61 -0
  343. ctpbee_api/rohon/include/new/rohon/ThostFtdcMdApi.h +168 -0
  344. ctpbee_api/rohon/include/new/rohon/ThostFtdcTraderApi.h +739 -0
  345. ctpbee_api/rohon/include/new/rohon/ThostFtdcUserApiDataType.h +6708 -0
  346. ctpbee_api/rohon/include/new/rohon/ThostFtdcUserApiStruct.h +9580 -0
  347. ctpbee_api/rohon/include/previous/pybind11/attr.h +489 -0
  348. ctpbee_api/rohon/include/previous/pybind11/buffer_info.h +108 -0
  349. ctpbee_api/rohon/include/previous/pybind11/cast.h +2067 -0
  350. ctpbee_api/rohon/include/previous/pybind11/chrono.h +162 -0
  351. ctpbee_api/rohon/include/previous/pybind11/common.h +2 -0
  352. ctpbee_api/rohon/include/previous/pybind11/complex.h +61 -0
  353. ctpbee_api/rohon/include/previous/pybind11/detail/class.h +626 -0
  354. ctpbee_api/rohon/include/previous/pybind11/detail/common.h +803 -0
  355. ctpbee_api/rohon/include/previous/pybind11/detail/descr.h +185 -0
  356. ctpbee_api/rohon/include/previous/pybind11/detail/init.h +335 -0
  357. ctpbee_api/rohon/include/previous/pybind11/detail/internals.h +285 -0
  358. ctpbee_api/rohon/include/previous/pybind11/detail/typeid.h +53 -0
  359. ctpbee_api/rohon/include/previous/pybind11/eigen.h +604 -0
  360. ctpbee_api/rohon/include/previous/pybind11/embed.h +194 -0
  361. ctpbee_api/rohon/include/previous/pybind11/eval.h +117 -0
  362. ctpbee_api/rohon/include/previous/pybind11/functional.h +85 -0
  363. ctpbee_api/rohon/include/previous/pybind11/iostream.h +200 -0
  364. ctpbee_api/rohon/include/previous/pybind11/numpy.h +1601 -0
  365. ctpbee_api/rohon/include/previous/pybind11/operators.h +168 -0
  366. ctpbee_api/rohon/include/previous/pybind11/options.h +65 -0
  367. ctpbee_api/rohon/include/previous/pybind11/pybind11.h +1965 -0
  368. ctpbee_api/rohon/include/previous/pybind11/pytypes.h +1332 -0
  369. ctpbee_api/rohon/include/previous/pybind11/stl.h +376 -0
  370. ctpbee_api/rohon/include/previous/pybind11/stl_bind.h +599 -0
  371. ctpbee_api/rohon/include/previous/rohon/ThostFtdcMdApi.h +168 -0
  372. ctpbee_api/rohon/include/previous/rohon/ThostFtdcTraderApi.h +739 -0
  373. ctpbee_api/rohon/include/previous/rohon/ThostFtdcUserApiDataType.h +6708 -0
  374. ctpbee_api/rohon/include/previous/rohon/ThostFtdcUserApiStruct.h +9580 -0
  375. ctpbee_api/rohon/libLinuxDataCollect.so +0 -0
  376. ctpbee_api/rohon/librohonbase.so +0 -0
  377. ctpbee_api/rohon/librohonbase.so.1.1 +0 -0
  378. ctpbee_api/rohon/librohonbase.so.1.1.0.1 +0 -0
  379. ctpbee_api/rohon/libs/thostmduserapi_se.lib +0 -0
  380. ctpbee_api/rohon/libs/thosttraderapi_se.lib +0 -0
  381. ctpbee_api/rohon/libthostmduserapi_se.so +0 -0
  382. ctpbee_api/rohon/libthosttraderapi_se.so +0 -0
  383. ctpbee_api/rohon/rohon_constant.py +1242 -0
  384. ctpbee_api/rohon/thostmduserapi_se.dll +0 -0
  385. ctpbee_api/rohon/thosttraderapi_se.dll +0 -0
  386. ctpbee_api/rohon/vnrohon/.vs/vnrohon/v15/.suo +0 -0
  387. ctpbee_api/rohon/vnrohon/.vs/vnrohon/v15/Browse.VC.db +0 -0
  388. ctpbee_api/rohon/vnrohon/.vs/vnrohon/v15/Solution.VC.db +0 -0
  389. ctpbee_api/rohon/vnrohon/vnrohon.h +147 -0
  390. ctpbee_api/rohon/vnrohon/vnrohon.sln +41 -0
  391. ctpbee_api/rohon/vnrohon/vnrohonmd/dllmain.cpp +19 -0
  392. ctpbee_api/rohon/vnrohon/vnrohonmd/framework.h +5 -0
  393. ctpbee_api/rohon/vnrohon/vnrohonmd/pch.cpp +5 -0
  394. ctpbee_api/rohon/vnrohon/vnrohonmd/pch.h +13 -0
  395. ctpbee_api/rohon/vnrohon/vnrohonmd/vnrohonmd.cpp +931 -0
  396. ctpbee_api/rohon/vnrohon/vnrohonmd/vnrohonmd.h +207 -0
  397. ctpbee_api/rohon/vnrohon/vnrohonmd/vnrohonmd.vcxproj +188 -0
  398. ctpbee_api/rohon/vnrohon/vnrohonmd/vnrohonmd.vcxproj.filters +54 -0
  399. ctpbee_api/rohon/vnrohon/vnrohonmd/vnrohonmd.vcxproj.user +4 -0
  400. ctpbee_api/rohon/vnrohon/vnrohontd/dllmain.cpp +19 -0
  401. ctpbee_api/rohon/vnrohon/vnrohontd/framework.h +5 -0
  402. ctpbee_api/rohon/vnrohon/vnrohontd/pch.cpp +5 -0
  403. ctpbee_api/rohon/vnrohon/vnrohontd/pch.h +13 -0
  404. ctpbee_api/rohon/vnrohon/vnrohontd/vnrohontd.cpp +11395 -0
  405. ctpbee_api/rohon/vnrohon/vnrohontd/vnrohontd.h +1259 -0
  406. ctpbee_api/rohon/vnrohon/vnrohontd/vnrohontd.vcxproj +188 -0
  407. ctpbee_api/rohon/vnrohon/vnrohontd/vnrohontd.vcxproj.filters +54 -0
  408. ctpbee_api/rohon/vnrohon/vnrohontd/vnrohontd.vcxproj.user +4 -0
  409. ctpbee_api/rohon/vnrohonmd.cp310-win_amd64.pyd +0 -0
  410. ctpbee_api/rohon/vnrohontd.cp310-win_amd64.pyd +0 -0
  411. ctpbee_opt_api-0.1.0.dist-info/METADATA +46 -0
  412. ctpbee_opt_api-0.1.0.dist-info/RECORD +414 -0
  413. ctpbee_opt_api-0.1.0.dist-info/WHEEL +5 -0
  414. ctpbee_opt_api-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1998 @@
1
+ /*
2
+ pybind11/numpy.h: Basic NumPy support, vectorize() wrapper
3
+
4
+ Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
+
6
+ All rights reserved. Use of this source code is governed by a
7
+ BSD-style license that can be found in the LICENSE file.
8
+ */
9
+
10
+ #pragma once
11
+
12
+ #include "pybind11.h"
13
+ #include "complex.h"
14
+
15
+ #include <algorithm>
16
+ #include <array>
17
+ #include <cstdint>
18
+ #include <cstdlib>
19
+ #include <cstring>
20
+ #include <functional>
21
+ #include <numeric>
22
+ #include <sstream>
23
+ #include <string>
24
+ #include <type_traits>
25
+ #include <typeindex>
26
+ #include <utility>
27
+ #include <vector>
28
+
29
+ /* This will be true on all flat address space platforms and allows us to reduce the
30
+ whole npy_intp / ssize_t / Py_intptr_t business down to just ssize_t for all size
31
+ and dimension types (e.g. shape, strides, indexing), instead of inflicting this
32
+ upon the library user. */
33
+ static_assert(sizeof(::pybind11::ssize_t) == sizeof(Py_intptr_t), "ssize_t != Py_intptr_t");
34
+ static_assert(std::is_signed<Py_intptr_t>::value, "Py_intptr_t must be signed");
35
+ // We now can reinterpret_cast between py::ssize_t and Py_intptr_t (MSVC + PyPy cares)
36
+
37
+ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
38
+
39
+ PYBIND11_WARNING_DISABLE_MSVC(4127)
40
+
41
+ class array; // Forward declaration
42
+
43
+ PYBIND11_NAMESPACE_BEGIN(detail)
44
+
45
+ template <>
46
+ struct handle_type_name<array> {
47
+ static constexpr auto name = const_name("numpy.ndarray");
48
+ };
49
+
50
+ template <typename type, typename SFINAE = void>
51
+ struct npy_format_descriptor;
52
+
53
+ struct PyArrayDescr_Proxy {
54
+ PyObject_HEAD
55
+ PyObject *typeobj;
56
+ char kind;
57
+ char type;
58
+ char byteorder;
59
+ char flags;
60
+ int type_num;
61
+ int elsize;
62
+ int alignment;
63
+ char *subarray;
64
+ PyObject *fields;
65
+ PyObject *names;
66
+ };
67
+
68
+ struct PyArray_Proxy {
69
+ PyObject_HEAD
70
+ char *data;
71
+ int nd;
72
+ ssize_t *dimensions;
73
+ ssize_t *strides;
74
+ PyObject *base;
75
+ PyObject *descr;
76
+ int flags;
77
+ };
78
+
79
+ struct PyVoidScalarObject_Proxy {
80
+ PyObject_VAR_HEAD char *obval;
81
+ PyArrayDescr_Proxy *descr;
82
+ int flags;
83
+ PyObject *base;
84
+ };
85
+
86
+ struct numpy_type_info {
87
+ PyObject *dtype_ptr;
88
+ std::string format_str;
89
+ };
90
+
91
+ struct numpy_internals {
92
+ std::unordered_map<std::type_index, numpy_type_info> registered_dtypes;
93
+
94
+ numpy_type_info *get_type_info(const std::type_info &tinfo, bool throw_if_missing = true) {
95
+ auto it = registered_dtypes.find(std::type_index(tinfo));
96
+ if (it != registered_dtypes.end()) {
97
+ return &(it->second);
98
+ }
99
+ if (throw_if_missing) {
100
+ pybind11_fail(std::string("NumPy type info missing for ") + tinfo.name());
101
+ }
102
+ return nullptr;
103
+ }
104
+
105
+ template <typename T>
106
+ numpy_type_info *get_type_info(bool throw_if_missing = true) {
107
+ return get_type_info(typeid(typename std::remove_cv<T>::type), throw_if_missing);
108
+ }
109
+ };
110
+
111
+ PYBIND11_NOINLINE void load_numpy_internals(numpy_internals *&ptr) {
112
+ ptr = &get_or_create_shared_data<numpy_internals>("_numpy_internals");
113
+ }
114
+
115
+ inline numpy_internals &get_numpy_internals() {
116
+ static numpy_internals *ptr = nullptr;
117
+ if (!ptr) {
118
+ load_numpy_internals(ptr);
119
+ }
120
+ return *ptr;
121
+ }
122
+
123
+ template <typename T>
124
+ struct same_size {
125
+ template <typename U>
126
+ using as = bool_constant<sizeof(T) == sizeof(U)>;
127
+ };
128
+
129
+ template <typename Concrete>
130
+ constexpr int platform_lookup() {
131
+ return -1;
132
+ }
133
+
134
+ // Lookup a type according to its size, and return a value corresponding to the NumPy typenum.
135
+ template <typename Concrete, typename T, typename... Ts, typename... Ints>
136
+ constexpr int platform_lookup(int I, Ints... Is) {
137
+ return sizeof(Concrete) == sizeof(T) ? I : platform_lookup<Concrete, Ts...>(Is...);
138
+ }
139
+
140
+ struct npy_api {
141
+ enum constants {
142
+ NPY_ARRAY_C_CONTIGUOUS_ = 0x0001,
143
+ NPY_ARRAY_F_CONTIGUOUS_ = 0x0002,
144
+ NPY_ARRAY_OWNDATA_ = 0x0004,
145
+ NPY_ARRAY_FORCECAST_ = 0x0010,
146
+ NPY_ARRAY_ENSUREARRAY_ = 0x0040,
147
+ NPY_ARRAY_ALIGNED_ = 0x0100,
148
+ NPY_ARRAY_WRITEABLE_ = 0x0400,
149
+ NPY_BOOL_ = 0,
150
+ NPY_BYTE_,
151
+ NPY_UBYTE_,
152
+ NPY_SHORT_,
153
+ NPY_USHORT_,
154
+ NPY_INT_,
155
+ NPY_UINT_,
156
+ NPY_LONG_,
157
+ NPY_ULONG_,
158
+ NPY_LONGLONG_,
159
+ NPY_ULONGLONG_,
160
+ NPY_FLOAT_,
161
+ NPY_DOUBLE_,
162
+ NPY_LONGDOUBLE_,
163
+ NPY_CFLOAT_,
164
+ NPY_CDOUBLE_,
165
+ NPY_CLONGDOUBLE_,
166
+ NPY_OBJECT_ = 17,
167
+ NPY_STRING_,
168
+ NPY_UNICODE_,
169
+ NPY_VOID_,
170
+ // Platform-dependent normalization
171
+ NPY_INT8_ = NPY_BYTE_,
172
+ NPY_UINT8_ = NPY_UBYTE_,
173
+ NPY_INT16_ = NPY_SHORT_,
174
+ NPY_UINT16_ = NPY_USHORT_,
175
+ // `npy_common.h` defines the integer aliases. In order, it checks:
176
+ // NPY_BITSOF_LONG, NPY_BITSOF_LONGLONG, NPY_BITSOF_INT, NPY_BITSOF_SHORT, NPY_BITSOF_CHAR
177
+ // and assigns the alias to the first matching size, so we should check in this order.
178
+ NPY_INT32_
179
+ = platform_lookup<std::int32_t, long, int, short>(NPY_LONG_, NPY_INT_, NPY_SHORT_),
180
+ NPY_UINT32_ = platform_lookup<std::uint32_t, unsigned long, unsigned int, unsigned short>(
181
+ NPY_ULONG_, NPY_UINT_, NPY_USHORT_),
182
+ NPY_INT64_
183
+ = platform_lookup<std::int64_t, long, long long, int>(NPY_LONG_, NPY_LONGLONG_, NPY_INT_),
184
+ NPY_UINT64_
185
+ = platform_lookup<std::uint64_t, unsigned long, unsigned long long, unsigned int>(
186
+ NPY_ULONG_, NPY_ULONGLONG_, NPY_UINT_),
187
+ };
188
+
189
+ struct PyArray_Dims {
190
+ Py_intptr_t *ptr;
191
+ int len;
192
+ };
193
+
194
+ static npy_api &get() {
195
+ static npy_api api = lookup();
196
+ return api;
197
+ }
198
+
199
+ bool PyArray_Check_(PyObject *obj) const {
200
+ return PyObject_TypeCheck(obj, PyArray_Type_) != 0;
201
+ }
202
+ bool PyArrayDescr_Check_(PyObject *obj) const {
203
+ return PyObject_TypeCheck(obj, PyArrayDescr_Type_) != 0;
204
+ }
205
+
206
+ unsigned int (*PyArray_GetNDArrayCFeatureVersion_)();
207
+ PyObject *(*PyArray_DescrFromType_)(int);
208
+ PyObject *(*PyArray_NewFromDescr_)(PyTypeObject *,
209
+ PyObject *,
210
+ int,
211
+ Py_intptr_t const *,
212
+ Py_intptr_t const *,
213
+ void *,
214
+ int,
215
+ PyObject *);
216
+ // Unused. Not removed because that affects ABI of the class.
217
+ PyObject *(*PyArray_DescrNewFromType_)(int);
218
+ int (*PyArray_CopyInto_)(PyObject *, PyObject *);
219
+ PyObject *(*PyArray_NewCopy_)(PyObject *, int);
220
+ PyTypeObject *PyArray_Type_;
221
+ PyTypeObject *PyVoidArrType_Type_;
222
+ PyTypeObject *PyArrayDescr_Type_;
223
+ PyObject *(*PyArray_DescrFromScalar_)(PyObject *);
224
+ PyObject *(*PyArray_FromAny_)(PyObject *, PyObject *, int, int, int, PyObject *);
225
+ int (*PyArray_DescrConverter_)(PyObject *, PyObject **);
226
+ bool (*PyArray_EquivTypes_)(PyObject *, PyObject *);
227
+ int (*PyArray_GetArrayParamsFromObject_)(PyObject *,
228
+ PyObject *,
229
+ unsigned char,
230
+ PyObject **,
231
+ int *,
232
+ Py_intptr_t *,
233
+ PyObject **,
234
+ PyObject *);
235
+ PyObject *(*PyArray_Squeeze_)(PyObject *);
236
+ // Unused. Not removed because that affects ABI of the class.
237
+ int (*PyArray_SetBaseObject_)(PyObject *, PyObject *);
238
+ PyObject *(*PyArray_Resize_)(PyObject *, PyArray_Dims *, int, int);
239
+ PyObject *(*PyArray_Newshape_)(PyObject *, PyArray_Dims *, int);
240
+ PyObject *(*PyArray_View_)(PyObject *, PyObject *, PyObject *);
241
+
242
+ private:
243
+ enum functions {
244
+ API_PyArray_GetNDArrayCFeatureVersion = 211,
245
+ API_PyArray_Type = 2,
246
+ API_PyArrayDescr_Type = 3,
247
+ API_PyVoidArrType_Type = 39,
248
+ API_PyArray_DescrFromType = 45,
249
+ API_PyArray_DescrFromScalar = 57,
250
+ API_PyArray_FromAny = 69,
251
+ API_PyArray_Resize = 80,
252
+ API_PyArray_CopyInto = 82,
253
+ API_PyArray_NewCopy = 85,
254
+ API_PyArray_NewFromDescr = 94,
255
+ API_PyArray_DescrNewFromType = 96,
256
+ API_PyArray_Newshape = 135,
257
+ API_PyArray_Squeeze = 136,
258
+ API_PyArray_View = 137,
259
+ API_PyArray_DescrConverter = 174,
260
+ API_PyArray_EquivTypes = 182,
261
+ API_PyArray_GetArrayParamsFromObject = 278,
262
+ API_PyArray_SetBaseObject = 282
263
+ };
264
+
265
+ static npy_api lookup() {
266
+ module_ m = module_::import("numpy.core.multiarray");
267
+ auto c = m.attr("_ARRAY_API");
268
+ void **api_ptr = (void **) PyCapsule_GetPointer(c.ptr(), nullptr);
269
+ npy_api api;
270
+ #define DECL_NPY_API(Func) api.Func##_ = (decltype(api.Func##_)) api_ptr[API_##Func];
271
+ DECL_NPY_API(PyArray_GetNDArrayCFeatureVersion);
272
+ if (api.PyArray_GetNDArrayCFeatureVersion_() < 0x7) {
273
+ pybind11_fail("pybind11 numpy support requires numpy >= 1.7.0");
274
+ }
275
+ DECL_NPY_API(PyArray_Type);
276
+ DECL_NPY_API(PyVoidArrType_Type);
277
+ DECL_NPY_API(PyArrayDescr_Type);
278
+ DECL_NPY_API(PyArray_DescrFromType);
279
+ DECL_NPY_API(PyArray_DescrFromScalar);
280
+ DECL_NPY_API(PyArray_FromAny);
281
+ DECL_NPY_API(PyArray_Resize);
282
+ DECL_NPY_API(PyArray_CopyInto);
283
+ DECL_NPY_API(PyArray_NewCopy);
284
+ DECL_NPY_API(PyArray_NewFromDescr);
285
+ DECL_NPY_API(PyArray_DescrNewFromType);
286
+ DECL_NPY_API(PyArray_Newshape);
287
+ DECL_NPY_API(PyArray_Squeeze);
288
+ DECL_NPY_API(PyArray_View);
289
+ DECL_NPY_API(PyArray_DescrConverter);
290
+ DECL_NPY_API(PyArray_EquivTypes);
291
+ DECL_NPY_API(PyArray_GetArrayParamsFromObject);
292
+ DECL_NPY_API(PyArray_SetBaseObject);
293
+
294
+ #undef DECL_NPY_API
295
+ return api;
296
+ }
297
+ };
298
+
299
+ inline PyArray_Proxy *array_proxy(void *ptr) { return reinterpret_cast<PyArray_Proxy *>(ptr); }
300
+
301
+ inline const PyArray_Proxy *array_proxy(const void *ptr) {
302
+ return reinterpret_cast<const PyArray_Proxy *>(ptr);
303
+ }
304
+
305
+ inline PyArrayDescr_Proxy *array_descriptor_proxy(PyObject *ptr) {
306
+ return reinterpret_cast<PyArrayDescr_Proxy *>(ptr);
307
+ }
308
+
309
+ inline const PyArrayDescr_Proxy *array_descriptor_proxy(const PyObject *ptr) {
310
+ return reinterpret_cast<const PyArrayDescr_Proxy *>(ptr);
311
+ }
312
+
313
+ inline bool check_flags(const void *ptr, int flag) {
314
+ return (flag == (array_proxy(ptr)->flags & flag));
315
+ }
316
+
317
+ template <typename T>
318
+ struct is_std_array : std::false_type {};
319
+ template <typename T, size_t N>
320
+ struct is_std_array<std::array<T, N>> : std::true_type {};
321
+ template <typename T>
322
+ struct is_complex : std::false_type {};
323
+ template <typename T>
324
+ struct is_complex<std::complex<T>> : std::true_type {};
325
+
326
+ template <typename T>
327
+ struct array_info_scalar {
328
+ using type = T;
329
+ static constexpr bool is_array = false;
330
+ static constexpr bool is_empty = false;
331
+ static constexpr auto extents = const_name("");
332
+ static void append_extents(list & /* shape */) {}
333
+ };
334
+ // Computes underlying type and a comma-separated list of extents for array
335
+ // types (any mix of std::array and built-in arrays). An array of char is
336
+ // treated as scalar because it gets special handling.
337
+ template <typename T>
338
+ struct array_info : array_info_scalar<T> {};
339
+ template <typename T, size_t N>
340
+ struct array_info<std::array<T, N>> {
341
+ using type = typename array_info<T>::type;
342
+ static constexpr bool is_array = true;
343
+ static constexpr bool is_empty = (N == 0) || array_info<T>::is_empty;
344
+ static constexpr size_t extent = N;
345
+
346
+ // appends the extents to shape
347
+ static void append_extents(list &shape) {
348
+ shape.append(N);
349
+ array_info<T>::append_extents(shape);
350
+ }
351
+
352
+ static constexpr auto extents = const_name<array_info<T>::is_array>(
353
+ concat(const_name<N>(), array_info<T>::extents), const_name<N>());
354
+ };
355
+ // For numpy we have special handling for arrays of characters, so we don't include
356
+ // the size in the array extents.
357
+ template <size_t N>
358
+ struct array_info<char[N]> : array_info_scalar<char[N]> {};
359
+ template <size_t N>
360
+ struct array_info<std::array<char, N>> : array_info_scalar<std::array<char, N>> {};
361
+ template <typename T, size_t N>
362
+ struct array_info<T[N]> : array_info<std::array<T, N>> {};
363
+ template <typename T>
364
+ using remove_all_extents_t = typename array_info<T>::type;
365
+
366
+ template <typename T>
367
+ using is_pod_struct
368
+ = all_of<std::is_standard_layout<T>, // since we're accessing directly in memory
369
+ // we need a standard layout type
370
+ #if defined(__GLIBCXX__) \
371
+ && (__GLIBCXX__ < 20150422 || __GLIBCXX__ == 20150426 || __GLIBCXX__ == 20150623 \
372
+ || __GLIBCXX__ == 20150626 || __GLIBCXX__ == 20160803)
373
+ // libstdc++ < 5 (including versions 4.8.5, 4.9.3 and 4.9.4 which were released after
374
+ // 5) don't implement is_trivially_copyable, so approximate it
375
+ std::is_trivially_destructible<T>,
376
+ satisfies_any_of<T, std::has_trivial_copy_constructor, std::has_trivial_copy_assign>,
377
+ #else
378
+ std::is_trivially_copyable<T>,
379
+ #endif
380
+ satisfies_none_of<T,
381
+ std::is_reference,
382
+ std::is_array,
383
+ is_std_array,
384
+ std::is_arithmetic,
385
+ is_complex,
386
+ std::is_enum>>;
387
+
388
+ // Replacement for std::is_pod (deprecated in C++20)
389
+ template <typename T>
390
+ using is_pod = all_of<std::is_standard_layout<T>, std::is_trivial<T>>;
391
+
392
+ template <ssize_t Dim = 0, typename Strides>
393
+ ssize_t byte_offset_unsafe(const Strides &) {
394
+ return 0;
395
+ }
396
+ template <ssize_t Dim = 0, typename Strides, typename... Ix>
397
+ ssize_t byte_offset_unsafe(const Strides &strides, ssize_t i, Ix... index) {
398
+ return i * strides[Dim] + byte_offset_unsafe<Dim + 1>(strides, index...);
399
+ }
400
+
401
+ /**
402
+ * Proxy class providing unsafe, unchecked const access to array data. This is constructed through
403
+ * the `unchecked<T, N>()` method of `array` or the `unchecked<N>()` method of `array_t<T>`. `Dims`
404
+ * will be -1 for dimensions determined at runtime.
405
+ */
406
+ template <typename T, ssize_t Dims>
407
+ class unchecked_reference {
408
+ protected:
409
+ static constexpr bool Dynamic = Dims < 0;
410
+ const unsigned char *data_;
411
+ // Storing the shape & strides in local variables (i.e. these arrays) allows the compiler to
412
+ // make large performance gains on big, nested loops, but requires compile-time dimensions
413
+ conditional_t<Dynamic, const ssize_t *, std::array<ssize_t, (size_t) Dims>> shape_, strides_;
414
+ const ssize_t dims_;
415
+
416
+ friend class pybind11::array;
417
+ // Constructor for compile-time dimensions:
418
+ template <bool Dyn = Dynamic>
419
+ unchecked_reference(const void *data,
420
+ const ssize_t *shape,
421
+ const ssize_t *strides,
422
+ enable_if_t<!Dyn, ssize_t>)
423
+ : data_{reinterpret_cast<const unsigned char *>(data)}, dims_{Dims} {
424
+ for (size_t i = 0; i < (size_t) dims_; i++) {
425
+ shape_[i] = shape[i];
426
+ strides_[i] = strides[i];
427
+ }
428
+ }
429
+ // Constructor for runtime dimensions:
430
+ template <bool Dyn = Dynamic>
431
+ unchecked_reference(const void *data,
432
+ const ssize_t *shape,
433
+ const ssize_t *strides,
434
+ enable_if_t<Dyn, ssize_t> dims)
435
+ : data_{reinterpret_cast<const unsigned char *>(data)}, shape_{shape}, strides_{strides},
436
+ dims_{dims} {}
437
+
438
+ public:
439
+ /**
440
+ * Unchecked const reference access to data at the given indices. For a compile-time known
441
+ * number of dimensions, this requires the correct number of arguments; for run-time
442
+ * dimensionality, this is not checked (and so is up to the caller to use safely).
443
+ */
444
+ template <typename... Ix>
445
+ const T &operator()(Ix... index) const {
446
+ static_assert(ssize_t{sizeof...(Ix)} == Dims || Dynamic,
447
+ "Invalid number of indices for unchecked array reference");
448
+ return *reinterpret_cast<const T *>(data_
449
+ + byte_offset_unsafe(strides_, ssize_t(index)...));
450
+ }
451
+ /**
452
+ * Unchecked const reference access to data; this operator only participates if the reference
453
+ * is to a 1-dimensional array. When present, this is exactly equivalent to `obj(index)`.
454
+ */
455
+ template <ssize_t D = Dims, typename = enable_if_t<D == 1 || Dynamic>>
456
+ const T &operator[](ssize_t index) const {
457
+ return operator()(index);
458
+ }
459
+
460
+ /// Pointer access to the data at the given indices.
461
+ template <typename... Ix>
462
+ const T *data(Ix... ix) const {
463
+ return &operator()(ssize_t(ix)...);
464
+ }
465
+
466
+ /// Returns the item size, i.e. sizeof(T)
467
+ constexpr static ssize_t itemsize() { return sizeof(T); }
468
+
469
+ /// Returns the shape (i.e. size) of dimension `dim`
470
+ ssize_t shape(ssize_t dim) const { return shape_[(size_t) dim]; }
471
+
472
+ /// Returns the number of dimensions of the array
473
+ ssize_t ndim() const { return dims_; }
474
+
475
+ /// Returns the total number of elements in the referenced array, i.e. the product of the
476
+ /// shapes
477
+ template <bool Dyn = Dynamic>
478
+ enable_if_t<!Dyn, ssize_t> size() const {
479
+ return std::accumulate(
480
+ shape_.begin(), shape_.end(), (ssize_t) 1, std::multiplies<ssize_t>());
481
+ }
482
+ template <bool Dyn = Dynamic>
483
+ enable_if_t<Dyn, ssize_t> size() const {
484
+ return std::accumulate(shape_, shape_ + ndim(), (ssize_t) 1, std::multiplies<ssize_t>());
485
+ }
486
+
487
+ /// Returns the total number of bytes used by the referenced data. Note that the actual span
488
+ /// in memory may be larger if the referenced array has non-contiguous strides (e.g. for a
489
+ /// slice).
490
+ ssize_t nbytes() const { return size() * itemsize(); }
491
+ };
492
+
493
+ template <typename T, ssize_t Dims>
494
+ class unchecked_mutable_reference : public unchecked_reference<T, Dims> {
495
+ friend class pybind11::array;
496
+ using ConstBase = unchecked_reference<T, Dims>;
497
+ using ConstBase::ConstBase;
498
+ using ConstBase::Dynamic;
499
+
500
+ public:
501
+ // Bring in const-qualified versions from base class
502
+ using ConstBase::operator();
503
+ using ConstBase::operator[];
504
+
505
+ /// Mutable, unchecked access to data at the given indices.
506
+ template <typename... Ix>
507
+ T &operator()(Ix... index) {
508
+ static_assert(ssize_t{sizeof...(Ix)} == Dims || Dynamic,
509
+ "Invalid number of indices for unchecked array reference");
510
+ return const_cast<T &>(ConstBase::operator()(index...));
511
+ }
512
+ /**
513
+ * Mutable, unchecked access data at the given index; this operator only participates if the
514
+ * reference is to a 1-dimensional array (or has runtime dimensions). When present, this is
515
+ * exactly equivalent to `obj(index)`.
516
+ */
517
+ template <ssize_t D = Dims, typename = enable_if_t<D == 1 || Dynamic>>
518
+ T &operator[](ssize_t index) {
519
+ return operator()(index);
520
+ }
521
+
522
+ /// Mutable pointer access to the data at the given indices.
523
+ template <typename... Ix>
524
+ T *mutable_data(Ix... ix) {
525
+ return &operator()(ssize_t(ix)...);
526
+ }
527
+ };
528
+
529
+ template <typename T, ssize_t Dim>
530
+ struct type_caster<unchecked_reference<T, Dim>> {
531
+ static_assert(Dim == 0 && Dim > 0 /* always fail */,
532
+ "unchecked array proxy object is not castable");
533
+ };
534
+ template <typename T, ssize_t Dim>
535
+ struct type_caster<unchecked_mutable_reference<T, Dim>>
536
+ : type_caster<unchecked_reference<T, Dim>> {};
537
+
538
+ PYBIND11_NAMESPACE_END(detail)
539
+
540
+ class dtype : public object {
541
+ public:
542
+ PYBIND11_OBJECT_DEFAULT(dtype, object, detail::npy_api::get().PyArrayDescr_Check_)
543
+
544
+ explicit dtype(const buffer_info &info) {
545
+ dtype descr(_dtype_from_pep3118()(pybind11::str(info.format)));
546
+ // If info.itemsize == 0, use the value calculated from the format string
547
+ m_ptr = descr.strip_padding(info.itemsize != 0 ? info.itemsize : descr.itemsize())
548
+ .release()
549
+ .ptr();
550
+ }
551
+
552
+ explicit dtype(const pybind11::str &format) : dtype(from_args(format)) {}
553
+
554
+ explicit dtype(const std::string &format) : dtype(pybind11::str(format)) {}
555
+
556
+ explicit dtype(const char *format) : dtype(pybind11::str(format)) {}
557
+
558
+ dtype(list names, list formats, list offsets, ssize_t itemsize) {
559
+ dict args;
560
+ args["names"] = std::move(names);
561
+ args["formats"] = std::move(formats);
562
+ args["offsets"] = std::move(offsets);
563
+ args["itemsize"] = pybind11::int_(itemsize);
564
+ m_ptr = from_args(args).release().ptr();
565
+ }
566
+
567
+ /// Return dtype for the given typenum (one of the NPY_TYPES).
568
+ /// https://numpy.org/devdocs/reference/c-api/array.html#c.PyArray_DescrFromType
569
+ explicit dtype(int typenum)
570
+ : object(detail::npy_api::get().PyArray_DescrFromType_(typenum), stolen_t{}) {
571
+ if (m_ptr == nullptr) {
572
+ throw error_already_set();
573
+ }
574
+ }
575
+
576
+ /// This is essentially the same as calling numpy.dtype(args) in Python.
577
+ static dtype from_args(const object &args) {
578
+ PyObject *ptr = nullptr;
579
+ if ((detail::npy_api::get().PyArray_DescrConverter_(args.ptr(), &ptr) == 0) || !ptr) {
580
+ throw error_already_set();
581
+ }
582
+ return reinterpret_steal<dtype>(ptr);
583
+ }
584
+
585
+ /// Return dtype associated with a C++ type.
586
+ template <typename T>
587
+ static dtype of() {
588
+ return detail::npy_format_descriptor<typename std::remove_cv<T>::type>::dtype();
589
+ }
590
+
591
+ /// Size of the data type in bytes.
592
+ ssize_t itemsize() const { return detail::array_descriptor_proxy(m_ptr)->elsize; }
593
+
594
+ /// Returns true for structured data types.
595
+ bool has_fields() const { return detail::array_descriptor_proxy(m_ptr)->names != nullptr; }
596
+
597
+ /// Single-character code for dtype's kind.
598
+ /// For example, floating point types are 'f' and integral types are 'i'.
599
+ char kind() const { return detail::array_descriptor_proxy(m_ptr)->kind; }
600
+
601
+ /// Single-character for dtype's type.
602
+ /// For example, ``float`` is 'f', ``double`` 'd', ``int`` 'i', and ``long`` 'l'.
603
+ char char_() const {
604
+ // Note: The signature, `dtype::char_` follows the naming of NumPy's
605
+ // public Python API (i.e., ``dtype.char``), rather than its internal
606
+ // C API (``PyArray_Descr::type``).
607
+ return detail::array_descriptor_proxy(m_ptr)->type;
608
+ }
609
+
610
+ /// type number of dtype.
611
+ int num() const {
612
+ // Note: The signature, `dtype::num` follows the naming of NumPy's public
613
+ // Python API (i.e., ``dtype.num``), rather than its internal
614
+ // C API (``PyArray_Descr::type_num``).
615
+ return detail::array_descriptor_proxy(m_ptr)->type_num;
616
+ }
617
+
618
+ /// Single character for byteorder
619
+ char byteorder() const { return detail::array_descriptor_proxy(m_ptr)->byteorder; }
620
+
621
+ /// Alignment of the data type
622
+ int alignment() const { return detail::array_descriptor_proxy(m_ptr)->alignment; }
623
+
624
+ /// Flags for the array descriptor
625
+ char flags() const { return detail::array_descriptor_proxy(m_ptr)->flags; }
626
+
627
+ private:
628
+ static object _dtype_from_pep3118() {
629
+ static PyObject *obj = module_::import("numpy.core._internal")
630
+ .attr("_dtype_from_pep3118")
631
+ .cast<object>()
632
+ .release()
633
+ .ptr();
634
+ return reinterpret_borrow<object>(obj);
635
+ }
636
+
637
+ dtype strip_padding(ssize_t itemsize) {
638
+ // Recursively strip all void fields with empty names that are generated for
639
+ // padding fields (as of NumPy v1.11).
640
+ if (!has_fields()) {
641
+ return *this;
642
+ }
643
+
644
+ struct field_descr {
645
+ pybind11::str name;
646
+ object format;
647
+ pybind11::int_ offset;
648
+ field_descr(pybind11::str &&name, object &&format, pybind11::int_ &&offset)
649
+ : name{std::move(name)}, format{std::move(format)}, offset{std::move(offset)} {};
650
+ };
651
+ auto field_dict = attr("fields").cast<dict>();
652
+ std::vector<field_descr> field_descriptors;
653
+ field_descriptors.reserve(field_dict.size());
654
+
655
+ for (auto field : field_dict.attr("items")()) {
656
+ auto spec = field.cast<tuple>();
657
+ auto name = spec[0].cast<pybind11::str>();
658
+ auto spec_fo = spec[1].cast<tuple>();
659
+ auto format = spec_fo[0].cast<dtype>();
660
+ auto offset = spec_fo[1].cast<pybind11::int_>();
661
+ if ((len(name) == 0u) && format.kind() == 'V') {
662
+ continue;
663
+ }
664
+ field_descriptors.emplace_back(
665
+ std::move(name), format.strip_padding(format.itemsize()), std::move(offset));
666
+ }
667
+
668
+ std::sort(field_descriptors.begin(),
669
+ field_descriptors.end(),
670
+ [](const field_descr &a, const field_descr &b) {
671
+ return a.offset.cast<int>() < b.offset.cast<int>();
672
+ });
673
+
674
+ list names, formats, offsets;
675
+ for (auto &descr : field_descriptors) {
676
+ names.append(std::move(descr.name));
677
+ formats.append(std::move(descr.format));
678
+ offsets.append(std::move(descr.offset));
679
+ }
680
+ return dtype(std::move(names), std::move(formats), std::move(offsets), itemsize);
681
+ }
682
+ };
683
+
684
+ class array : public buffer {
685
+ public:
686
+ PYBIND11_OBJECT_CVT(array, buffer, detail::npy_api::get().PyArray_Check_, raw_array)
687
+
688
+ enum {
689
+ c_style = detail::npy_api::NPY_ARRAY_C_CONTIGUOUS_,
690
+ f_style = detail::npy_api::NPY_ARRAY_F_CONTIGUOUS_,
691
+ forcecast = detail::npy_api::NPY_ARRAY_FORCECAST_
692
+ };
693
+
694
+ array() : array(0, static_cast<const double *>(nullptr)) {}
695
+
696
+ using ShapeContainer = detail::any_container<ssize_t>;
697
+ using StridesContainer = detail::any_container<ssize_t>;
698
+
699
+ // Constructs an array taking shape/strides from arbitrary container types
700
+ array(const pybind11::dtype &dt,
701
+ ShapeContainer shape,
702
+ StridesContainer strides,
703
+ const void *ptr = nullptr,
704
+ handle base = handle()) {
705
+
706
+ if (strides->empty()) {
707
+ *strides = detail::c_strides(*shape, dt.itemsize());
708
+ }
709
+
710
+ auto ndim = shape->size();
711
+ if (ndim != strides->size()) {
712
+ pybind11_fail("NumPy: shape ndim doesn't match strides ndim");
713
+ }
714
+ auto descr = dt;
715
+
716
+ int flags = 0;
717
+ if (base && ptr) {
718
+ if (isinstance<array>(base)) {
719
+ /* Copy flags from base (except ownership bit) */
720
+ flags = reinterpret_borrow<array>(base).flags()
721
+ & ~detail::npy_api::NPY_ARRAY_OWNDATA_;
722
+ } else {
723
+ /* Writable by default, easy to downgrade later on if needed */
724
+ flags = detail::npy_api::NPY_ARRAY_WRITEABLE_;
725
+ }
726
+ }
727
+
728
+ auto &api = detail::npy_api::get();
729
+ auto tmp = reinterpret_steal<object>(api.PyArray_NewFromDescr_(
730
+ api.PyArray_Type_,
731
+ descr.release().ptr(),
732
+ (int) ndim,
733
+ // Use reinterpret_cast for PyPy on Windows (remove if fixed, checked on 7.3.1)
734
+ reinterpret_cast<Py_intptr_t *>(shape->data()),
735
+ reinterpret_cast<Py_intptr_t *>(strides->data()),
736
+ const_cast<void *>(ptr),
737
+ flags,
738
+ nullptr));
739
+ if (!tmp) {
740
+ throw error_already_set();
741
+ }
742
+ if (ptr) {
743
+ if (base) {
744
+ api.PyArray_SetBaseObject_(tmp.ptr(), base.inc_ref().ptr());
745
+ } else {
746
+ tmp = reinterpret_steal<object>(
747
+ api.PyArray_NewCopy_(tmp.ptr(), -1 /* any order */));
748
+ }
749
+ }
750
+ m_ptr = tmp.release().ptr();
751
+ }
752
+
753
+ array(const pybind11::dtype &dt,
754
+ ShapeContainer shape,
755
+ const void *ptr = nullptr,
756
+ handle base = handle())
757
+ : array(dt, std::move(shape), {}, ptr, base) {}
758
+
759
+ template <typename T,
760
+ typename
761
+ = detail::enable_if_t<std::is_integral<T>::value && !std::is_same<bool, T>::value>>
762
+ array(const pybind11::dtype &dt, T count, const void *ptr = nullptr, handle base = handle())
763
+ : array(dt, {{count}}, ptr, base) {}
764
+
765
+ template <typename T>
766
+ array(ShapeContainer shape, StridesContainer strides, const T *ptr, handle base = handle())
767
+ : array(pybind11::dtype::of<T>(), std::move(shape), std::move(strides), ptr, base) {}
768
+
769
+ template <typename T>
770
+ array(ShapeContainer shape, const T *ptr, handle base = handle())
771
+ : array(std::move(shape), {}, ptr, base) {}
772
+
773
+ template <typename T>
774
+ explicit array(ssize_t count, const T *ptr, handle base = handle())
775
+ : array({count}, {}, ptr, base) {}
776
+
777
+ explicit array(const buffer_info &info, handle base = handle())
778
+ : array(pybind11::dtype(info), info.shape, info.strides, info.ptr, base) {}
779
+
780
+ /// Array descriptor (dtype)
781
+ pybind11::dtype dtype() const {
782
+ return reinterpret_borrow<pybind11::dtype>(detail::array_proxy(m_ptr)->descr);
783
+ }
784
+
785
+ /// Total number of elements
786
+ ssize_t size() const {
787
+ return std::accumulate(shape(), shape() + ndim(), (ssize_t) 1, std::multiplies<ssize_t>());
788
+ }
789
+
790
+ /// Byte size of a single element
791
+ ssize_t itemsize() const {
792
+ return detail::array_descriptor_proxy(detail::array_proxy(m_ptr)->descr)->elsize;
793
+ }
794
+
795
+ /// Total number of bytes
796
+ ssize_t nbytes() const { return size() * itemsize(); }
797
+
798
+ /// Number of dimensions
799
+ ssize_t ndim() const { return detail::array_proxy(m_ptr)->nd; }
800
+
801
+ /// Base object
802
+ object base() const { return reinterpret_borrow<object>(detail::array_proxy(m_ptr)->base); }
803
+
804
+ /// Dimensions of the array
805
+ const ssize_t *shape() const { return detail::array_proxy(m_ptr)->dimensions; }
806
+
807
+ /// Dimension along a given axis
808
+ ssize_t shape(ssize_t dim) const {
809
+ if (dim >= ndim()) {
810
+ fail_dim_check(dim, "invalid axis");
811
+ }
812
+ return shape()[dim];
813
+ }
814
+
815
+ /// Strides of the array
816
+ const ssize_t *strides() const { return detail::array_proxy(m_ptr)->strides; }
817
+
818
+ /// Stride along a given axis
819
+ ssize_t strides(ssize_t dim) const {
820
+ if (dim >= ndim()) {
821
+ fail_dim_check(dim, "invalid axis");
822
+ }
823
+ return strides()[dim];
824
+ }
825
+
826
+ /// Return the NumPy array flags
827
+ int flags() const { return detail::array_proxy(m_ptr)->flags; }
828
+
829
+ /// If set, the array is writeable (otherwise the buffer is read-only)
830
+ bool writeable() const {
831
+ return detail::check_flags(m_ptr, detail::npy_api::NPY_ARRAY_WRITEABLE_);
832
+ }
833
+
834
+ /// If set, the array owns the data (will be freed when the array is deleted)
835
+ bool owndata() const {
836
+ return detail::check_flags(m_ptr, detail::npy_api::NPY_ARRAY_OWNDATA_);
837
+ }
838
+
839
+ /// Pointer to the contained data. If index is not provided, points to the
840
+ /// beginning of the buffer. May throw if the index would lead to out of bounds access.
841
+ template <typename... Ix>
842
+ const void *data(Ix... index) const {
843
+ return static_cast<const void *>(detail::array_proxy(m_ptr)->data + offset_at(index...));
844
+ }
845
+
846
+ /// Mutable pointer to the contained data. If index is not provided, points to the
847
+ /// beginning of the buffer. May throw if the index would lead to out of bounds access.
848
+ /// May throw if the array is not writeable.
849
+ template <typename... Ix>
850
+ void *mutable_data(Ix... index) {
851
+ check_writeable();
852
+ return static_cast<void *>(detail::array_proxy(m_ptr)->data + offset_at(index...));
853
+ }
854
+
855
+ /// Byte offset from beginning of the array to a given index (full or partial).
856
+ /// May throw if the index would lead to out of bounds access.
857
+ template <typename... Ix>
858
+ ssize_t offset_at(Ix... index) const {
859
+ if ((ssize_t) sizeof...(index) > ndim()) {
860
+ fail_dim_check(sizeof...(index), "too many indices for an array");
861
+ }
862
+ return byte_offset(ssize_t(index)...);
863
+ }
864
+
865
+ ssize_t offset_at() const { return 0; }
866
+
867
+ /// Item count from beginning of the array to a given index (full or partial).
868
+ /// May throw if the index would lead to out of bounds access.
869
+ template <typename... Ix>
870
+ ssize_t index_at(Ix... index) const {
871
+ return offset_at(index...) / itemsize();
872
+ }
873
+
874
+ /**
875
+ * Returns a proxy object that provides access to the array's data without bounds or
876
+ * dimensionality checking. Will throw if the array is missing the `writeable` flag. Use with
877
+ * care: the array must not be destroyed or reshaped for the duration of the returned object,
878
+ * and the caller must take care not to access invalid dimensions or dimension indices.
879
+ */
880
+ template <typename T, ssize_t Dims = -1>
881
+ detail::unchecked_mutable_reference<T, Dims> mutable_unchecked() & {
882
+ if (Dims >= 0 && ndim() != Dims) {
883
+ throw std::domain_error("array has incorrect number of dimensions: "
884
+ + std::to_string(ndim()) + "; expected "
885
+ + std::to_string(Dims));
886
+ }
887
+ return detail::unchecked_mutable_reference<T, Dims>(
888
+ mutable_data(), shape(), strides(), ndim());
889
+ }
890
+
891
+ /**
892
+ * Returns a proxy object that provides const access to the array's data without bounds or
893
+ * dimensionality checking. Unlike `mutable_unchecked()`, this does not require that the
894
+ * underlying array have the `writable` flag. Use with care: the array must not be destroyed
895
+ * or reshaped for the duration of the returned object, and the caller must take care not to
896
+ * access invalid dimensions or dimension indices.
897
+ */
898
+ template <typename T, ssize_t Dims = -1>
899
+ detail::unchecked_reference<T, Dims> unchecked() const & {
900
+ if (Dims >= 0 && ndim() != Dims) {
901
+ throw std::domain_error("array has incorrect number of dimensions: "
902
+ + std::to_string(ndim()) + "; expected "
903
+ + std::to_string(Dims));
904
+ }
905
+ return detail::unchecked_reference<T, Dims>(data(), shape(), strides(), ndim());
906
+ }
907
+
908
+ /// Return a new view with all of the dimensions of length 1 removed
909
+ array squeeze() {
910
+ auto &api = detail::npy_api::get();
911
+ return reinterpret_steal<array>(api.PyArray_Squeeze_(m_ptr));
912
+ }
913
+
914
+ /// Resize array to given shape
915
+ /// If refcheck is true and more that one reference exist to this array
916
+ /// then resize will succeed only if it makes a reshape, i.e. original size doesn't change
917
+ void resize(ShapeContainer new_shape, bool refcheck = true) {
918
+ detail::npy_api::PyArray_Dims d
919
+ = {// Use reinterpret_cast for PyPy on Windows (remove if fixed, checked on 7.3.1)
920
+ reinterpret_cast<Py_intptr_t *>(new_shape->data()),
921
+ int(new_shape->size())};
922
+ // try to resize, set ordering param to -1 cause it's not used anyway
923
+ auto new_array = reinterpret_steal<object>(
924
+ detail::npy_api::get().PyArray_Resize_(m_ptr, &d, int(refcheck), -1));
925
+ if (!new_array) {
926
+ throw error_already_set();
927
+ }
928
+ if (isinstance<array>(new_array)) {
929
+ *this = std::move(new_array);
930
+ }
931
+ }
932
+
933
+ /// Optional `order` parameter omitted, to be added as needed.
934
+ array reshape(ShapeContainer new_shape) {
935
+ detail::npy_api::PyArray_Dims d
936
+ = {reinterpret_cast<Py_intptr_t *>(new_shape->data()), int(new_shape->size())};
937
+ auto new_array
938
+ = reinterpret_steal<array>(detail::npy_api::get().PyArray_Newshape_(m_ptr, &d, 0));
939
+ if (!new_array) {
940
+ throw error_already_set();
941
+ }
942
+ return new_array;
943
+ }
944
+
945
+ /// Create a view of an array in a different data type.
946
+ /// This function may fundamentally reinterpret the data in the array.
947
+ /// It is the responsibility of the caller to ensure that this is safe.
948
+ /// Only supports the `dtype` argument, the `type` argument is omitted,
949
+ /// to be added as needed.
950
+ array view(const std::string &dtype) {
951
+ auto &api = detail::npy_api::get();
952
+ auto new_view = reinterpret_steal<array>(api.PyArray_View_(
953
+ m_ptr, dtype::from_args(pybind11::str(dtype)).release().ptr(), nullptr));
954
+ if (!new_view) {
955
+ throw error_already_set();
956
+ }
957
+ return new_view;
958
+ }
959
+
960
+ /// Ensure that the argument is a NumPy array
961
+ /// In case of an error, nullptr is returned and the Python error is cleared.
962
+ static array ensure(handle h, int ExtraFlags = 0) {
963
+ auto result = reinterpret_steal<array>(raw_array(h.ptr(), ExtraFlags));
964
+ if (!result) {
965
+ PyErr_Clear();
966
+ }
967
+ return result;
968
+ }
969
+
970
+ protected:
971
+ template <typename, typename>
972
+ friend struct detail::npy_format_descriptor;
973
+
974
+ void fail_dim_check(ssize_t dim, const std::string &msg) const {
975
+ throw index_error(msg + ": " + std::to_string(dim) + " (ndim = " + std::to_string(ndim())
976
+ + ')');
977
+ }
978
+
979
+ template <typename... Ix>
980
+ ssize_t byte_offset(Ix... index) const {
981
+ check_dimensions(index...);
982
+ return detail::byte_offset_unsafe(strides(), ssize_t(index)...);
983
+ }
984
+
985
+ void check_writeable() const {
986
+ if (!writeable()) {
987
+ throw std::domain_error("array is not writeable");
988
+ }
989
+ }
990
+
991
+ template <typename... Ix>
992
+ void check_dimensions(Ix... index) const {
993
+ check_dimensions_impl(ssize_t(0), shape(), ssize_t(index)...);
994
+ }
995
+
996
+ void check_dimensions_impl(ssize_t, const ssize_t *) const {}
997
+
998
+ template <typename... Ix>
999
+ void check_dimensions_impl(ssize_t axis, const ssize_t *shape, ssize_t i, Ix... index) const {
1000
+ if (i >= *shape) {
1001
+ throw index_error(std::string("index ") + std::to_string(i)
1002
+ + " is out of bounds for axis " + std::to_string(axis)
1003
+ + " with size " + std::to_string(*shape));
1004
+ }
1005
+ check_dimensions_impl(axis + 1, shape + 1, index...);
1006
+ }
1007
+
1008
+ /// Create array from any object -- always returns a new reference
1009
+ static PyObject *raw_array(PyObject *ptr, int ExtraFlags = 0) {
1010
+ if (ptr == nullptr) {
1011
+ PyErr_SetString(PyExc_ValueError, "cannot create a pybind11::array from a nullptr");
1012
+ return nullptr;
1013
+ }
1014
+ return detail::npy_api::get().PyArray_FromAny_(
1015
+ ptr, nullptr, 0, 0, detail::npy_api::NPY_ARRAY_ENSUREARRAY_ | ExtraFlags, nullptr);
1016
+ }
1017
+ };
1018
+
1019
+ template <typename T, int ExtraFlags = array::forcecast>
1020
+ class array_t : public array {
1021
+ private:
1022
+ struct private_ctor {};
1023
+ // Delegating constructor needed when both moving and accessing in the same constructor
1024
+ array_t(private_ctor,
1025
+ ShapeContainer &&shape,
1026
+ StridesContainer &&strides,
1027
+ const T *ptr,
1028
+ handle base)
1029
+ : array(std::move(shape), std::move(strides), ptr, base) {}
1030
+
1031
+ public:
1032
+ static_assert(!detail::array_info<T>::is_array, "Array types cannot be used with array_t");
1033
+
1034
+ using value_type = T;
1035
+
1036
+ array_t() : array(0, static_cast<const T *>(nullptr)) {}
1037
+ array_t(handle h, borrowed_t) : array(h, borrowed_t{}) {}
1038
+ array_t(handle h, stolen_t) : array(h, stolen_t{}) {}
1039
+
1040
+ PYBIND11_DEPRECATED("Use array_t<T>::ensure() instead")
1041
+ array_t(handle h, bool is_borrowed) : array(raw_array_t(h.ptr()), stolen_t{}) {
1042
+ if (!m_ptr) {
1043
+ PyErr_Clear();
1044
+ }
1045
+ if (!is_borrowed) {
1046
+ Py_XDECREF(h.ptr());
1047
+ }
1048
+ }
1049
+
1050
+ // NOLINTNEXTLINE(google-explicit-constructor)
1051
+ array_t(const object &o) : array(raw_array_t(o.ptr()), stolen_t{}) {
1052
+ if (!m_ptr) {
1053
+ throw error_already_set();
1054
+ }
1055
+ }
1056
+
1057
+ explicit array_t(const buffer_info &info, handle base = handle()) : array(info, base) {}
1058
+
1059
+ array_t(ShapeContainer shape,
1060
+ StridesContainer strides,
1061
+ const T *ptr = nullptr,
1062
+ handle base = handle())
1063
+ : array(std::move(shape), std::move(strides), ptr, base) {}
1064
+
1065
+ explicit array_t(ShapeContainer shape, const T *ptr = nullptr, handle base = handle())
1066
+ : array_t(private_ctor{},
1067
+ std::move(shape),
1068
+ (ExtraFlags & f_style) != 0 ? detail::f_strides(*shape, itemsize())
1069
+ : detail::c_strides(*shape, itemsize()),
1070
+ ptr,
1071
+ base) {}
1072
+
1073
+ explicit array_t(ssize_t count, const T *ptr = nullptr, handle base = handle())
1074
+ : array({count}, {}, ptr, base) {}
1075
+
1076
+ constexpr ssize_t itemsize() const { return sizeof(T); }
1077
+
1078
+ template <typename... Ix>
1079
+ ssize_t index_at(Ix... index) const {
1080
+ return offset_at(index...) / itemsize();
1081
+ }
1082
+
1083
+ template <typename... Ix>
1084
+ const T *data(Ix... index) const {
1085
+ return static_cast<const T *>(array::data(index...));
1086
+ }
1087
+
1088
+ template <typename... Ix>
1089
+ T *mutable_data(Ix... index) {
1090
+ return static_cast<T *>(array::mutable_data(index...));
1091
+ }
1092
+
1093
+ // Reference to element at a given index
1094
+ template <typename... Ix>
1095
+ const T &at(Ix... index) const {
1096
+ if ((ssize_t) sizeof...(index) != ndim()) {
1097
+ fail_dim_check(sizeof...(index), "index dimension mismatch");
1098
+ }
1099
+ return *(static_cast<const T *>(array::data())
1100
+ + byte_offset(ssize_t(index)...) / itemsize());
1101
+ }
1102
+
1103
+ // Mutable reference to element at a given index
1104
+ template <typename... Ix>
1105
+ T &mutable_at(Ix... index) {
1106
+ if ((ssize_t) sizeof...(index) != ndim()) {
1107
+ fail_dim_check(sizeof...(index), "index dimension mismatch");
1108
+ }
1109
+ return *(static_cast<T *>(array::mutable_data())
1110
+ + byte_offset(ssize_t(index)...) / itemsize());
1111
+ }
1112
+
1113
+ /**
1114
+ * Returns a proxy object that provides access to the array's data without bounds or
1115
+ * dimensionality checking. Will throw if the array is missing the `writeable` flag. Use with
1116
+ * care: the array must not be destroyed or reshaped for the duration of the returned object,
1117
+ * and the caller must take care not to access invalid dimensions or dimension indices.
1118
+ */
1119
+ template <ssize_t Dims = -1>
1120
+ detail::unchecked_mutable_reference<T, Dims> mutable_unchecked() & {
1121
+ return array::mutable_unchecked<T, Dims>();
1122
+ }
1123
+
1124
+ /**
1125
+ * Returns a proxy object that provides const access to the array's data without bounds or
1126
+ * dimensionality checking. Unlike `mutable_unchecked()`, this does not require that the
1127
+ * underlying array have the `writable` flag. Use with care: the array must not be destroyed
1128
+ * or reshaped for the duration of the returned object, and the caller must take care not to
1129
+ * access invalid dimensions or dimension indices.
1130
+ */
1131
+ template <ssize_t Dims = -1>
1132
+ detail::unchecked_reference<T, Dims> unchecked() const & {
1133
+ return array::unchecked<T, Dims>();
1134
+ }
1135
+
1136
+ /// Ensure that the argument is a NumPy array of the correct dtype (and if not, try to convert
1137
+ /// it). In case of an error, nullptr is returned and the Python error is cleared.
1138
+ static array_t ensure(handle h) {
1139
+ auto result = reinterpret_steal<array_t>(raw_array_t(h.ptr()));
1140
+ if (!result) {
1141
+ PyErr_Clear();
1142
+ }
1143
+ return result;
1144
+ }
1145
+
1146
+ static bool check_(handle h) {
1147
+ const auto &api = detail::npy_api::get();
1148
+ return api.PyArray_Check_(h.ptr())
1149
+ && api.PyArray_EquivTypes_(detail::array_proxy(h.ptr())->descr,
1150
+ dtype::of<T>().ptr())
1151
+ && detail::check_flags(h.ptr(), ExtraFlags & (array::c_style | array::f_style));
1152
+ }
1153
+
1154
+ protected:
1155
+ /// Create array from any object -- always returns a new reference
1156
+ static PyObject *raw_array_t(PyObject *ptr) {
1157
+ if (ptr == nullptr) {
1158
+ PyErr_SetString(PyExc_ValueError, "cannot create a pybind11::array_t from a nullptr");
1159
+ return nullptr;
1160
+ }
1161
+ return detail::npy_api::get().PyArray_FromAny_(ptr,
1162
+ dtype::of<T>().release().ptr(),
1163
+ 0,
1164
+ 0,
1165
+ detail::npy_api::NPY_ARRAY_ENSUREARRAY_
1166
+ | ExtraFlags,
1167
+ nullptr);
1168
+ }
1169
+ };
1170
+
1171
+ template <typename T>
1172
+ struct format_descriptor<T, detail::enable_if_t<detail::is_pod_struct<T>::value>> {
1173
+ static std::string format() {
1174
+ return detail::npy_format_descriptor<typename std::remove_cv<T>::type>::format();
1175
+ }
1176
+ };
1177
+
1178
+ template <size_t N>
1179
+ struct format_descriptor<char[N]> {
1180
+ static std::string format() { return std::to_string(N) + 's'; }
1181
+ };
1182
+ template <size_t N>
1183
+ struct format_descriptor<std::array<char, N>> {
1184
+ static std::string format() { return std::to_string(N) + 's'; }
1185
+ };
1186
+
1187
+ template <typename T>
1188
+ struct format_descriptor<T, detail::enable_if_t<std::is_enum<T>::value>> {
1189
+ static std::string format() {
1190
+ return format_descriptor<
1191
+ typename std::remove_cv<typename std::underlying_type<T>::type>::type>::format();
1192
+ }
1193
+ };
1194
+
1195
+ template <typename T>
1196
+ struct format_descriptor<T, detail::enable_if_t<detail::array_info<T>::is_array>> {
1197
+ static std::string format() {
1198
+ using namespace detail;
1199
+ static constexpr auto extents = const_name("(") + array_info<T>::extents + const_name(")");
1200
+ return extents.text + format_descriptor<remove_all_extents_t<T>>::format();
1201
+ }
1202
+ };
1203
+
1204
+ PYBIND11_NAMESPACE_BEGIN(detail)
1205
+ template <typename T, int ExtraFlags>
1206
+ struct pyobject_caster<array_t<T, ExtraFlags>> {
1207
+ using type = array_t<T, ExtraFlags>;
1208
+
1209
+ bool load(handle src, bool convert) {
1210
+ if (!convert && !type::check_(src)) {
1211
+ return false;
1212
+ }
1213
+ value = type::ensure(src);
1214
+ return static_cast<bool>(value);
1215
+ }
1216
+
1217
+ static handle cast(const handle &src, return_value_policy /* policy */, handle /* parent */) {
1218
+ return src.inc_ref();
1219
+ }
1220
+ PYBIND11_TYPE_CASTER(type, handle_type_name<type>::name);
1221
+ };
1222
+
1223
+ template <typename T>
1224
+ struct compare_buffer_info<T, detail::enable_if_t<detail::is_pod_struct<T>::value>> {
1225
+ static bool compare(const buffer_info &b) {
1226
+ return npy_api::get().PyArray_EquivTypes_(dtype::of<T>().ptr(), dtype(b).ptr());
1227
+ }
1228
+ };
1229
+
1230
+ template <typename T, typename = void>
1231
+ struct npy_format_descriptor_name;
1232
+
1233
+ template <typename T>
1234
+ struct npy_format_descriptor_name<T, enable_if_t<std::is_integral<T>::value>> {
1235
+ static constexpr auto name = const_name<std::is_same<T, bool>::value>(
1236
+ const_name("bool"),
1237
+ const_name<std::is_signed<T>::value>("numpy.int", "numpy.uint")
1238
+ + const_name<sizeof(T) * 8>());
1239
+ };
1240
+
1241
+ template <typename T>
1242
+ struct npy_format_descriptor_name<T, enable_if_t<std::is_floating_point<T>::value>> {
1243
+ static constexpr auto name = const_name < std::is_same<T, float>::value
1244
+ || std::is_same<T, const float>::value
1245
+ || std::is_same<T, double>::value
1246
+ || std::is_same<T, const double>::value
1247
+ > (const_name("numpy.float") + const_name<sizeof(T) * 8>(),
1248
+ const_name("numpy.longdouble"));
1249
+ };
1250
+
1251
+ template <typename T>
1252
+ struct npy_format_descriptor_name<T, enable_if_t<is_complex<T>::value>> {
1253
+ static constexpr auto name = const_name < std::is_same<typename T::value_type, float>::value
1254
+ || std::is_same<typename T::value_type, const float>::value
1255
+ || std::is_same<typename T::value_type, double>::value
1256
+ || std::is_same<typename T::value_type, const double>::value
1257
+ > (const_name("numpy.complex")
1258
+ + const_name<sizeof(typename T::value_type) * 16>(),
1259
+ const_name("numpy.longcomplex"));
1260
+ };
1261
+
1262
+ template <typename T>
1263
+ struct npy_format_descriptor<
1264
+ T,
1265
+ enable_if_t<satisfies_any_of<T, std::is_arithmetic, is_complex>::value>>
1266
+ : npy_format_descriptor_name<T> {
1267
+ private:
1268
+ // NB: the order here must match the one in common.h
1269
+ constexpr static const int values[15] = {npy_api::NPY_BOOL_,
1270
+ npy_api::NPY_BYTE_,
1271
+ npy_api::NPY_UBYTE_,
1272
+ npy_api::NPY_INT16_,
1273
+ npy_api::NPY_UINT16_,
1274
+ npy_api::NPY_INT32_,
1275
+ npy_api::NPY_UINT32_,
1276
+ npy_api::NPY_INT64_,
1277
+ npy_api::NPY_UINT64_,
1278
+ npy_api::NPY_FLOAT_,
1279
+ npy_api::NPY_DOUBLE_,
1280
+ npy_api::NPY_LONGDOUBLE_,
1281
+ npy_api::NPY_CFLOAT_,
1282
+ npy_api::NPY_CDOUBLE_,
1283
+ npy_api::NPY_CLONGDOUBLE_};
1284
+
1285
+ public:
1286
+ static constexpr int value = values[detail::is_fmt_numeric<T>::index];
1287
+
1288
+ static pybind11::dtype dtype() { return pybind11::dtype(/*typenum*/ value); }
1289
+ };
1290
+
1291
+ template <typename T>
1292
+ struct npy_format_descriptor<T, enable_if_t<is_same_ignoring_cvref<T, PyObject *>::value>> {
1293
+ static constexpr auto name = const_name("object");
1294
+
1295
+ static constexpr int value = npy_api::NPY_OBJECT_;
1296
+
1297
+ static pybind11::dtype dtype() { return pybind11::dtype(/*typenum*/ value); }
1298
+ };
1299
+
1300
+ #define PYBIND11_DECL_CHAR_FMT \
1301
+ static constexpr auto name = const_name("S") + const_name<N>(); \
1302
+ static pybind11::dtype dtype() { \
1303
+ return pybind11::dtype(std::string("S") + std::to_string(N)); \
1304
+ }
1305
+ template <size_t N>
1306
+ struct npy_format_descriptor<char[N]> {
1307
+ PYBIND11_DECL_CHAR_FMT
1308
+ };
1309
+ template <size_t N>
1310
+ struct npy_format_descriptor<std::array<char, N>> {
1311
+ PYBIND11_DECL_CHAR_FMT
1312
+ };
1313
+ #undef PYBIND11_DECL_CHAR_FMT
1314
+
1315
+ template <typename T>
1316
+ struct npy_format_descriptor<T, enable_if_t<array_info<T>::is_array>> {
1317
+ private:
1318
+ using base_descr = npy_format_descriptor<typename array_info<T>::type>;
1319
+
1320
+ public:
1321
+ static_assert(!array_info<T>::is_empty, "Zero-sized arrays are not supported");
1322
+
1323
+ static constexpr auto name
1324
+ = const_name("(") + array_info<T>::extents + const_name(")") + base_descr::name;
1325
+ static pybind11::dtype dtype() {
1326
+ list shape;
1327
+ array_info<T>::append_extents(shape);
1328
+ return pybind11::dtype::from_args(
1329
+ pybind11::make_tuple(base_descr::dtype(), std::move(shape)));
1330
+ }
1331
+ };
1332
+
1333
+ template <typename T>
1334
+ struct npy_format_descriptor<T, enable_if_t<std::is_enum<T>::value>> {
1335
+ private:
1336
+ using base_descr = npy_format_descriptor<typename std::underlying_type<T>::type>;
1337
+
1338
+ public:
1339
+ static constexpr auto name = base_descr::name;
1340
+ static pybind11::dtype dtype() { return base_descr::dtype(); }
1341
+ };
1342
+
1343
+ struct field_descriptor {
1344
+ const char *name;
1345
+ ssize_t offset;
1346
+ ssize_t size;
1347
+ std::string format;
1348
+ dtype descr;
1349
+ };
1350
+
1351
+ PYBIND11_NOINLINE void register_structured_dtype(any_container<field_descriptor> fields,
1352
+ const std::type_info &tinfo,
1353
+ ssize_t itemsize,
1354
+ bool (*direct_converter)(PyObject *, void *&)) {
1355
+
1356
+ auto &numpy_internals = get_numpy_internals();
1357
+ if (numpy_internals.get_type_info(tinfo, false)) {
1358
+ pybind11_fail("NumPy: dtype is already registered");
1359
+ }
1360
+
1361
+ // Use ordered fields because order matters as of NumPy 1.14:
1362
+ // https://docs.scipy.org/doc/numpy/release.html#multiple-field-indexing-assignment-of-structured-arrays
1363
+ std::vector<field_descriptor> ordered_fields(std::move(fields));
1364
+ std::sort(
1365
+ ordered_fields.begin(),
1366
+ ordered_fields.end(),
1367
+ [](const field_descriptor &a, const field_descriptor &b) { return a.offset < b.offset; });
1368
+
1369
+ list names, formats, offsets;
1370
+ for (auto &field : ordered_fields) {
1371
+ if (!field.descr) {
1372
+ pybind11_fail(std::string("NumPy: unsupported field dtype: `") + field.name + "` @ "
1373
+ + tinfo.name());
1374
+ }
1375
+ names.append(pybind11::str(field.name));
1376
+ formats.append(field.descr);
1377
+ offsets.append(pybind11::int_(field.offset));
1378
+ }
1379
+ auto *dtype_ptr
1380
+ = pybind11::dtype(std::move(names), std::move(formats), std::move(offsets), itemsize)
1381
+ .release()
1382
+ .ptr();
1383
+
1384
+ // There is an existing bug in NumPy (as of v1.11): trailing bytes are
1385
+ // not encoded explicitly into the format string. This will supposedly
1386
+ // get fixed in v1.12; for further details, see these:
1387
+ // - https://github.com/numpy/numpy/issues/7797
1388
+ // - https://github.com/numpy/numpy/pull/7798
1389
+ // Because of this, we won't use numpy's logic to generate buffer format
1390
+ // strings and will just do it ourselves.
1391
+ ssize_t offset = 0;
1392
+ std::ostringstream oss;
1393
+ // mark the structure as unaligned with '^', because numpy and C++ don't
1394
+ // always agree about alignment (particularly for complex), and we're
1395
+ // explicitly listing all our padding. This depends on none of the fields
1396
+ // overriding the endianness. Putting the ^ in front of individual fields
1397
+ // isn't guaranteed to work due to https://github.com/numpy/numpy/issues/9049
1398
+ oss << "^T{";
1399
+ for (auto &field : ordered_fields) {
1400
+ if (field.offset > offset) {
1401
+ oss << (field.offset - offset) << 'x';
1402
+ }
1403
+ oss << field.format << ':' << field.name << ':';
1404
+ offset = field.offset + field.size;
1405
+ }
1406
+ if (itemsize > offset) {
1407
+ oss << (itemsize - offset) << 'x';
1408
+ }
1409
+ oss << '}';
1410
+ auto format_str = oss.str();
1411
+
1412
+ // Smoke test: verify that NumPy properly parses our buffer format string
1413
+ auto &api = npy_api::get();
1414
+ auto arr = array(buffer_info(nullptr, itemsize, format_str, 1));
1415
+ if (!api.PyArray_EquivTypes_(dtype_ptr, arr.dtype().ptr())) {
1416
+ pybind11_fail("NumPy: invalid buffer descriptor!");
1417
+ }
1418
+
1419
+ auto tindex = std::type_index(tinfo);
1420
+ numpy_internals.registered_dtypes[tindex] = {dtype_ptr, std::move(format_str)};
1421
+ get_internals().direct_conversions[tindex].push_back(direct_converter);
1422
+ }
1423
+
1424
+ template <typename T, typename SFINAE>
1425
+ struct npy_format_descriptor {
1426
+ static_assert(is_pod_struct<T>::value,
1427
+ "Attempt to use a non-POD or unimplemented POD type as a numpy dtype");
1428
+
1429
+ static constexpr auto name = make_caster<T>::name;
1430
+
1431
+ static pybind11::dtype dtype() { return reinterpret_borrow<pybind11::dtype>(dtype_ptr()); }
1432
+
1433
+ static std::string format() {
1434
+ static auto format_str = get_numpy_internals().get_type_info<T>(true)->format_str;
1435
+ return format_str;
1436
+ }
1437
+
1438
+ static void register_dtype(any_container<field_descriptor> fields) {
1439
+ register_structured_dtype(std::move(fields),
1440
+ typeid(typename std::remove_cv<T>::type),
1441
+ sizeof(T),
1442
+ &direct_converter);
1443
+ }
1444
+
1445
+ private:
1446
+ static PyObject *dtype_ptr() {
1447
+ static PyObject *ptr = get_numpy_internals().get_type_info<T>(true)->dtype_ptr;
1448
+ return ptr;
1449
+ }
1450
+
1451
+ static bool direct_converter(PyObject *obj, void *&value) {
1452
+ auto &api = npy_api::get();
1453
+ if (!PyObject_TypeCheck(obj, api.PyVoidArrType_Type_)) {
1454
+ return false;
1455
+ }
1456
+ if (auto descr = reinterpret_steal<object>(api.PyArray_DescrFromScalar_(obj))) {
1457
+ if (api.PyArray_EquivTypes_(dtype_ptr(), descr.ptr())) {
1458
+ value = ((PyVoidScalarObject_Proxy *) obj)->obval;
1459
+ return true;
1460
+ }
1461
+ }
1462
+ return false;
1463
+ }
1464
+ };
1465
+
1466
+ #ifdef __CLION_IDE__ // replace heavy macro with dummy code for the IDE (doesn't affect code)
1467
+ # define PYBIND11_NUMPY_DTYPE(Type, ...) ((void) 0)
1468
+ # define PYBIND11_NUMPY_DTYPE_EX(Type, ...) ((void) 0)
1469
+ #else
1470
+
1471
+ # define PYBIND11_FIELD_DESCRIPTOR_EX(T, Field, Name) \
1472
+ ::pybind11::detail::field_descriptor { \
1473
+ Name, offsetof(T, Field), sizeof(decltype(std::declval<T>().Field)), \
1474
+ ::pybind11::format_descriptor<decltype(std::declval<T>().Field)>::format(), \
1475
+ ::pybind11::detail::npy_format_descriptor< \
1476
+ decltype(std::declval<T>().Field)>::dtype() \
1477
+ }
1478
+
1479
+ // Extract name, offset and format descriptor for a struct field
1480
+ # define PYBIND11_FIELD_DESCRIPTOR(T, Field) PYBIND11_FIELD_DESCRIPTOR_EX(T, Field, #Field)
1481
+
1482
+ // The main idea of this macro is borrowed from https://github.com/swansontec/map-macro
1483
+ // (C) William Swanson, Paul Fultz
1484
+ # define PYBIND11_EVAL0(...) __VA_ARGS__
1485
+ # define PYBIND11_EVAL1(...) PYBIND11_EVAL0(PYBIND11_EVAL0(PYBIND11_EVAL0(__VA_ARGS__)))
1486
+ # define PYBIND11_EVAL2(...) PYBIND11_EVAL1(PYBIND11_EVAL1(PYBIND11_EVAL1(__VA_ARGS__)))
1487
+ # define PYBIND11_EVAL3(...) PYBIND11_EVAL2(PYBIND11_EVAL2(PYBIND11_EVAL2(__VA_ARGS__)))
1488
+ # define PYBIND11_EVAL4(...) PYBIND11_EVAL3(PYBIND11_EVAL3(PYBIND11_EVAL3(__VA_ARGS__)))
1489
+ # define PYBIND11_EVAL(...) PYBIND11_EVAL4(PYBIND11_EVAL4(PYBIND11_EVAL4(__VA_ARGS__)))
1490
+ # define PYBIND11_MAP_END(...)
1491
+ # define PYBIND11_MAP_OUT
1492
+ # define PYBIND11_MAP_COMMA ,
1493
+ # define PYBIND11_MAP_GET_END() 0, PYBIND11_MAP_END
1494
+ # define PYBIND11_MAP_NEXT0(test, next, ...) next PYBIND11_MAP_OUT
1495
+ # define PYBIND11_MAP_NEXT1(test, next) PYBIND11_MAP_NEXT0(test, next, 0)
1496
+ # define PYBIND11_MAP_NEXT(test, next) PYBIND11_MAP_NEXT1(PYBIND11_MAP_GET_END test, next)
1497
+ # if defined(_MSC_VER) \
1498
+ && !defined(__clang__) // MSVC is not as eager to expand macros, hence this workaround
1499
+ # define PYBIND11_MAP_LIST_NEXT1(test, next) \
1500
+ PYBIND11_EVAL0(PYBIND11_MAP_NEXT0(test, PYBIND11_MAP_COMMA next, 0))
1501
+ # else
1502
+ # define PYBIND11_MAP_LIST_NEXT1(test, next) \
1503
+ PYBIND11_MAP_NEXT0(test, PYBIND11_MAP_COMMA next, 0)
1504
+ # endif
1505
+ # define PYBIND11_MAP_LIST_NEXT(test, next) \
1506
+ PYBIND11_MAP_LIST_NEXT1(PYBIND11_MAP_GET_END test, next)
1507
+ # define PYBIND11_MAP_LIST0(f, t, x, peek, ...) \
1508
+ f(t, x) PYBIND11_MAP_LIST_NEXT(peek, PYBIND11_MAP_LIST1)(f, t, peek, __VA_ARGS__)
1509
+ # define PYBIND11_MAP_LIST1(f, t, x, peek, ...) \
1510
+ f(t, x) PYBIND11_MAP_LIST_NEXT(peek, PYBIND11_MAP_LIST0)(f, t, peek, __VA_ARGS__)
1511
+ // PYBIND11_MAP_LIST(f, t, a1, a2, ...) expands to f(t, a1), f(t, a2), ...
1512
+ # define PYBIND11_MAP_LIST(f, t, ...) \
1513
+ PYBIND11_EVAL(PYBIND11_MAP_LIST1(f, t, __VA_ARGS__, (), 0))
1514
+
1515
+ # define PYBIND11_NUMPY_DTYPE(Type, ...) \
1516
+ ::pybind11::detail::npy_format_descriptor<Type>::register_dtype( \
1517
+ ::std::vector<::pybind11::detail::field_descriptor>{ \
1518
+ PYBIND11_MAP_LIST(PYBIND11_FIELD_DESCRIPTOR, Type, __VA_ARGS__)})
1519
+
1520
+ # if defined(_MSC_VER) && !defined(__clang__)
1521
+ # define PYBIND11_MAP2_LIST_NEXT1(test, next) \
1522
+ PYBIND11_EVAL0(PYBIND11_MAP_NEXT0(test, PYBIND11_MAP_COMMA next, 0))
1523
+ # else
1524
+ # define PYBIND11_MAP2_LIST_NEXT1(test, next) \
1525
+ PYBIND11_MAP_NEXT0(test, PYBIND11_MAP_COMMA next, 0)
1526
+ # endif
1527
+ # define PYBIND11_MAP2_LIST_NEXT(test, next) \
1528
+ PYBIND11_MAP2_LIST_NEXT1(PYBIND11_MAP_GET_END test, next)
1529
+ # define PYBIND11_MAP2_LIST0(f, t, x1, x2, peek, ...) \
1530
+ f(t, x1, x2) PYBIND11_MAP2_LIST_NEXT(peek, PYBIND11_MAP2_LIST1)(f, t, peek, __VA_ARGS__)
1531
+ # define PYBIND11_MAP2_LIST1(f, t, x1, x2, peek, ...) \
1532
+ f(t, x1, x2) PYBIND11_MAP2_LIST_NEXT(peek, PYBIND11_MAP2_LIST0)(f, t, peek, __VA_ARGS__)
1533
+ // PYBIND11_MAP2_LIST(f, t, a1, a2, ...) expands to f(t, a1, a2), f(t, a3, a4), ...
1534
+ # define PYBIND11_MAP2_LIST(f, t, ...) \
1535
+ PYBIND11_EVAL(PYBIND11_MAP2_LIST1(f, t, __VA_ARGS__, (), 0))
1536
+
1537
+ # define PYBIND11_NUMPY_DTYPE_EX(Type, ...) \
1538
+ ::pybind11::detail::npy_format_descriptor<Type>::register_dtype( \
1539
+ ::std::vector<::pybind11::detail::field_descriptor>{ \
1540
+ PYBIND11_MAP2_LIST(PYBIND11_FIELD_DESCRIPTOR_EX, Type, __VA_ARGS__)})
1541
+
1542
+ #endif // __CLION_IDE__
1543
+
1544
+ class common_iterator {
1545
+ public:
1546
+ using container_type = std::vector<ssize_t>;
1547
+ using value_type = container_type::value_type;
1548
+ using size_type = container_type::size_type;
1549
+
1550
+ common_iterator() : m_strides() {}
1551
+
1552
+ common_iterator(void *ptr, const container_type &strides, const container_type &shape)
1553
+ : p_ptr(reinterpret_cast<char *>(ptr)), m_strides(strides.size()) {
1554
+ m_strides.back() = static_cast<value_type>(strides.back());
1555
+ for (size_type i = m_strides.size() - 1; i != 0; --i) {
1556
+ size_type j = i - 1;
1557
+ auto s = static_cast<value_type>(shape[i]);
1558
+ m_strides[j] = strides[j] + m_strides[i] - strides[i] * s;
1559
+ }
1560
+ }
1561
+
1562
+ void increment(size_type dim) { p_ptr += m_strides[dim]; }
1563
+
1564
+ void *data() const { return p_ptr; }
1565
+
1566
+ private:
1567
+ char *p_ptr{nullptr};
1568
+ container_type m_strides;
1569
+ };
1570
+
1571
+ template <size_t N>
1572
+ class multi_array_iterator {
1573
+ public:
1574
+ using container_type = std::vector<ssize_t>;
1575
+
1576
+ multi_array_iterator(const std::array<buffer_info, N> &buffers, const container_type &shape)
1577
+ : m_shape(shape.size()), m_index(shape.size(), 0), m_common_iterator() {
1578
+
1579
+ // Manual copy to avoid conversion warning if using std::copy
1580
+ for (size_t i = 0; i < shape.size(); ++i) {
1581
+ m_shape[i] = shape[i];
1582
+ }
1583
+
1584
+ container_type strides(shape.size());
1585
+ for (size_t i = 0; i < N; ++i) {
1586
+ init_common_iterator(buffers[i], shape, m_common_iterator[i], strides);
1587
+ }
1588
+ }
1589
+
1590
+ multi_array_iterator &operator++() {
1591
+ for (size_t j = m_index.size(); j != 0; --j) {
1592
+ size_t i = j - 1;
1593
+ if (++m_index[i] != m_shape[i]) {
1594
+ increment_common_iterator(i);
1595
+ break;
1596
+ }
1597
+ m_index[i] = 0;
1598
+ }
1599
+ return *this;
1600
+ }
1601
+
1602
+ template <size_t K, class T = void>
1603
+ T *data() const {
1604
+ return reinterpret_cast<T *>(m_common_iterator[K].data());
1605
+ }
1606
+
1607
+ private:
1608
+ using common_iter = common_iterator;
1609
+
1610
+ void init_common_iterator(const buffer_info &buffer,
1611
+ const container_type &shape,
1612
+ common_iter &iterator,
1613
+ container_type &strides) {
1614
+ auto buffer_shape_iter = buffer.shape.rbegin();
1615
+ auto buffer_strides_iter = buffer.strides.rbegin();
1616
+ auto shape_iter = shape.rbegin();
1617
+ auto strides_iter = strides.rbegin();
1618
+
1619
+ while (buffer_shape_iter != buffer.shape.rend()) {
1620
+ if (*shape_iter == *buffer_shape_iter) {
1621
+ *strides_iter = *buffer_strides_iter;
1622
+ } else {
1623
+ *strides_iter = 0;
1624
+ }
1625
+
1626
+ ++buffer_shape_iter;
1627
+ ++buffer_strides_iter;
1628
+ ++shape_iter;
1629
+ ++strides_iter;
1630
+ }
1631
+
1632
+ std::fill(strides_iter, strides.rend(), 0);
1633
+ iterator = common_iter(buffer.ptr, strides, shape);
1634
+ }
1635
+
1636
+ void increment_common_iterator(size_t dim) {
1637
+ for (auto &iter : m_common_iterator) {
1638
+ iter.increment(dim);
1639
+ }
1640
+ }
1641
+
1642
+ container_type m_shape;
1643
+ container_type m_index;
1644
+ std::array<common_iter, N> m_common_iterator;
1645
+ };
1646
+
1647
+ enum class broadcast_trivial { non_trivial, c_trivial, f_trivial };
1648
+
1649
+ // Populates the shape and number of dimensions for the set of buffers. Returns a
1650
+ // broadcast_trivial enum value indicating whether the broadcast is "trivial"--that is, has each
1651
+ // buffer being either a singleton or a full-size, C-contiguous (`c_trivial`) or Fortran-contiguous
1652
+ // (`f_trivial`) storage buffer; returns `non_trivial` otherwise.
1653
+ template <size_t N>
1654
+ broadcast_trivial
1655
+ broadcast(const std::array<buffer_info, N> &buffers, ssize_t &ndim, std::vector<ssize_t> &shape) {
1656
+ ndim = std::accumulate(
1657
+ buffers.begin(), buffers.end(), ssize_t(0), [](ssize_t res, const buffer_info &buf) {
1658
+ return std::max(res, buf.ndim);
1659
+ });
1660
+
1661
+ shape.clear();
1662
+ shape.resize((size_t) ndim, 1);
1663
+
1664
+ // Figure out the output size, and make sure all input arrays conform (i.e. are either size 1
1665
+ // or the full size).
1666
+ for (size_t i = 0; i < N; ++i) {
1667
+ auto res_iter = shape.rbegin();
1668
+ auto end = buffers[i].shape.rend();
1669
+ for (auto shape_iter = buffers[i].shape.rbegin(); shape_iter != end;
1670
+ ++shape_iter, ++res_iter) {
1671
+ const auto &dim_size_in = *shape_iter;
1672
+ auto &dim_size_out = *res_iter;
1673
+
1674
+ // Each input dimension can either be 1 or `n`, but `n` values must match across
1675
+ // buffers
1676
+ if (dim_size_out == 1) {
1677
+ dim_size_out = dim_size_in;
1678
+ } else if (dim_size_in != 1 && dim_size_in != dim_size_out) {
1679
+ pybind11_fail("pybind11::vectorize: incompatible size/dimension of inputs!");
1680
+ }
1681
+ }
1682
+ }
1683
+
1684
+ bool trivial_broadcast_c = true;
1685
+ bool trivial_broadcast_f = true;
1686
+ for (size_t i = 0; i < N && (trivial_broadcast_c || trivial_broadcast_f); ++i) {
1687
+ if (buffers[i].size == 1) {
1688
+ continue;
1689
+ }
1690
+
1691
+ // Require the same number of dimensions:
1692
+ if (buffers[i].ndim != ndim) {
1693
+ return broadcast_trivial::non_trivial;
1694
+ }
1695
+
1696
+ // Require all dimensions be full-size:
1697
+ if (!std::equal(buffers[i].shape.cbegin(), buffers[i].shape.cend(), shape.cbegin())) {
1698
+ return broadcast_trivial::non_trivial;
1699
+ }
1700
+
1701
+ // Check for C contiguity (but only if previous inputs were also C contiguous)
1702
+ if (trivial_broadcast_c) {
1703
+ ssize_t expect_stride = buffers[i].itemsize;
1704
+ auto end = buffers[i].shape.crend();
1705
+ for (auto shape_iter = buffers[i].shape.crbegin(),
1706
+ stride_iter = buffers[i].strides.crbegin();
1707
+ trivial_broadcast_c && shape_iter != end;
1708
+ ++shape_iter, ++stride_iter) {
1709
+ if (expect_stride == *stride_iter) {
1710
+ expect_stride *= *shape_iter;
1711
+ } else {
1712
+ trivial_broadcast_c = false;
1713
+ }
1714
+ }
1715
+ }
1716
+
1717
+ // Check for Fortran contiguity (if previous inputs were also F contiguous)
1718
+ if (trivial_broadcast_f) {
1719
+ ssize_t expect_stride = buffers[i].itemsize;
1720
+ auto end = buffers[i].shape.cend();
1721
+ for (auto shape_iter = buffers[i].shape.cbegin(),
1722
+ stride_iter = buffers[i].strides.cbegin();
1723
+ trivial_broadcast_f && shape_iter != end;
1724
+ ++shape_iter, ++stride_iter) {
1725
+ if (expect_stride == *stride_iter) {
1726
+ expect_stride *= *shape_iter;
1727
+ } else {
1728
+ trivial_broadcast_f = false;
1729
+ }
1730
+ }
1731
+ }
1732
+ }
1733
+
1734
+ return trivial_broadcast_c ? broadcast_trivial::c_trivial
1735
+ : trivial_broadcast_f ? broadcast_trivial::f_trivial
1736
+ : broadcast_trivial::non_trivial;
1737
+ }
1738
+
1739
+ template <typename T>
1740
+ struct vectorize_arg {
1741
+ static_assert(!std::is_rvalue_reference<T>::value,
1742
+ "Functions with rvalue reference arguments cannot be vectorized");
1743
+ // The wrapped function gets called with this type:
1744
+ using call_type = remove_reference_t<T>;
1745
+ // Is this a vectorized argument?
1746
+ static constexpr bool vectorize
1747
+ = satisfies_any_of<call_type, std::is_arithmetic, is_complex, is_pod>::value
1748
+ && satisfies_none_of<call_type,
1749
+ std::is_pointer,
1750
+ std::is_array,
1751
+ is_std_array,
1752
+ std::is_enum>::value
1753
+ && (!std::is_reference<T>::value
1754
+ || (std::is_lvalue_reference<T>::value && std::is_const<call_type>::value));
1755
+ // Accept this type: an array for vectorized types, otherwise the type as-is:
1756
+ using type = conditional_t<vectorize, array_t<remove_cv_t<call_type>, array::forcecast>, T>;
1757
+ };
1758
+
1759
+ // py::vectorize when a return type is present
1760
+ template <typename Func, typename Return, typename... Args>
1761
+ struct vectorize_returned_array {
1762
+ using Type = array_t<Return>;
1763
+
1764
+ static Type create(broadcast_trivial trivial, const std::vector<ssize_t> &shape) {
1765
+ if (trivial == broadcast_trivial::f_trivial) {
1766
+ return array_t<Return, array::f_style>(shape);
1767
+ }
1768
+ return array_t<Return>(shape);
1769
+ }
1770
+
1771
+ static Return *mutable_data(Type &array) { return array.mutable_data(); }
1772
+
1773
+ static Return call(Func &f, Args &...args) { return f(args...); }
1774
+
1775
+ static void call(Return *out, size_t i, Func &f, Args &...args) { out[i] = f(args...); }
1776
+ };
1777
+
1778
+ // py::vectorize when a return type is not present
1779
+ template <typename Func, typename... Args>
1780
+ struct vectorize_returned_array<Func, void, Args...> {
1781
+ using Type = none;
1782
+
1783
+ static Type create(broadcast_trivial, const std::vector<ssize_t> &) { return none(); }
1784
+
1785
+ static void *mutable_data(Type &) { return nullptr; }
1786
+
1787
+ static detail::void_type call(Func &f, Args &...args) {
1788
+ f(args...);
1789
+ return {};
1790
+ }
1791
+
1792
+ static void call(void *, size_t, Func &f, Args &...args) { f(args...); }
1793
+ };
1794
+
1795
+ template <typename Func, typename Return, typename... Args>
1796
+ struct vectorize_helper {
1797
+
1798
+ // NVCC for some reason breaks if NVectorized is private
1799
+ #ifdef __CUDACC__
1800
+ public:
1801
+ #else
1802
+ private:
1803
+ #endif
1804
+
1805
+ static constexpr size_t N = sizeof...(Args);
1806
+ static constexpr size_t NVectorized = constexpr_sum(vectorize_arg<Args>::vectorize...);
1807
+ static_assert(
1808
+ NVectorized >= 1,
1809
+ "pybind11::vectorize(...) requires a function with at least one vectorizable argument");
1810
+
1811
+ public:
1812
+ template <typename T,
1813
+ // SFINAE to prevent shadowing the copy constructor.
1814
+ typename = detail::enable_if_t<
1815
+ !std::is_same<vectorize_helper, typename std::decay<T>::type>::value>>
1816
+ explicit vectorize_helper(T &&f) : f(std::forward<T>(f)) {}
1817
+
1818
+ object operator()(typename vectorize_arg<Args>::type... args) {
1819
+ return run(args...,
1820
+ make_index_sequence<N>(),
1821
+ select_indices<vectorize_arg<Args>::vectorize...>(),
1822
+ make_index_sequence<NVectorized>());
1823
+ }
1824
+
1825
+ private:
1826
+ remove_reference_t<Func> f;
1827
+
1828
+ // Internal compiler error in MSVC 19.16.27025.1 (Visual Studio 2017 15.9.4), when compiling
1829
+ // with "/permissive-" flag when arg_call_types is manually inlined.
1830
+ using arg_call_types = std::tuple<typename vectorize_arg<Args>::call_type...>;
1831
+ template <size_t Index>
1832
+ using param_n_t = typename std::tuple_element<Index, arg_call_types>::type;
1833
+
1834
+ using returned_array = vectorize_returned_array<Func, Return, Args...>;
1835
+
1836
+ // Runs a vectorized function given arguments tuple and three index sequences:
1837
+ // - Index is the full set of 0 ... (N-1) argument indices;
1838
+ // - VIndex is the subset of argument indices with vectorized parameters, letting us access
1839
+ // vectorized arguments (anything not in this sequence is passed through)
1840
+ // - BIndex is a incremental sequence (beginning at 0) of the same size as VIndex, so that
1841
+ // we can store vectorized buffer_infos in an array (argument VIndex has its buffer at
1842
+ // index BIndex in the array).
1843
+ template <size_t... Index, size_t... VIndex, size_t... BIndex>
1844
+ object run(typename vectorize_arg<Args>::type &...args,
1845
+ index_sequence<Index...> i_seq,
1846
+ index_sequence<VIndex...> vi_seq,
1847
+ index_sequence<BIndex...> bi_seq) {
1848
+
1849
+ // Pointers to values the function was called with; the vectorized ones set here will start
1850
+ // out as array_t<T> pointers, but they will be changed them to T pointers before we make
1851
+ // call the wrapped function. Non-vectorized pointers are left as-is.
1852
+ std::array<void *, N> params{{&args...}};
1853
+
1854
+ // The array of `buffer_info`s of vectorized arguments:
1855
+ std::array<buffer_info, NVectorized> buffers{
1856
+ {reinterpret_cast<array *>(params[VIndex])->request()...}};
1857
+
1858
+ /* Determine dimensions parameters of output array */
1859
+ ssize_t nd = 0;
1860
+ std::vector<ssize_t> shape(0);
1861
+ auto trivial = broadcast(buffers, nd, shape);
1862
+ auto ndim = (size_t) nd;
1863
+
1864
+ size_t size
1865
+ = std::accumulate(shape.begin(), shape.end(), (size_t) 1, std::multiplies<size_t>());
1866
+
1867
+ // If all arguments are 0-dimension arrays (i.e. single values) return a plain value (i.e.
1868
+ // not wrapped in an array).
1869
+ if (size == 1 && ndim == 0) {
1870
+ PYBIND11_EXPAND_SIDE_EFFECTS(params[VIndex] = buffers[BIndex].ptr);
1871
+ return cast(
1872
+ returned_array::call(f, *reinterpret_cast<param_n_t<Index> *>(params[Index])...));
1873
+ }
1874
+
1875
+ auto result = returned_array::create(trivial, shape);
1876
+
1877
+ PYBIND11_WARNING_PUSH
1878
+ #ifdef PYBIND11_DETECTED_CLANG_WITH_MISLEADING_CALL_STD_MOVE_EXPLICITLY_WARNING
1879
+ PYBIND11_WARNING_DISABLE_CLANG("-Wreturn-std-move")
1880
+ #endif
1881
+
1882
+ if (size == 0) {
1883
+ return result;
1884
+ }
1885
+
1886
+ /* Call the function */
1887
+ auto *mutable_data = returned_array::mutable_data(result);
1888
+ if (trivial == broadcast_trivial::non_trivial) {
1889
+ apply_broadcast(buffers, params, mutable_data, size, shape, i_seq, vi_seq, bi_seq);
1890
+ } else {
1891
+ apply_trivial(buffers, params, mutable_data, size, i_seq, vi_seq, bi_seq);
1892
+ }
1893
+
1894
+ return result;
1895
+ PYBIND11_WARNING_POP
1896
+ }
1897
+
1898
+ template <size_t... Index, size_t... VIndex, size_t... BIndex>
1899
+ void apply_trivial(std::array<buffer_info, NVectorized> &buffers,
1900
+ std::array<void *, N> &params,
1901
+ Return *out,
1902
+ size_t size,
1903
+ index_sequence<Index...>,
1904
+ index_sequence<VIndex...>,
1905
+ index_sequence<BIndex...>) {
1906
+
1907
+ // Initialize an array of mutable byte references and sizes with references set to the
1908
+ // appropriate pointer in `params`; as we iterate, we'll increment each pointer by its size
1909
+ // (except for singletons, which get an increment of 0).
1910
+ std::array<std::pair<unsigned char *&, const size_t>, NVectorized> vecparams{
1911
+ {std::pair<unsigned char *&, const size_t>(
1912
+ reinterpret_cast<unsigned char *&>(params[VIndex] = buffers[BIndex].ptr),
1913
+ buffers[BIndex].size == 1 ? 0 : sizeof(param_n_t<VIndex>))...}};
1914
+
1915
+ for (size_t i = 0; i < size; ++i) {
1916
+ returned_array::call(
1917
+ out, i, f, *reinterpret_cast<param_n_t<Index> *>(params[Index])...);
1918
+ for (auto &x : vecparams) {
1919
+ x.first += x.second;
1920
+ }
1921
+ }
1922
+ }
1923
+
1924
+ template <size_t... Index, size_t... VIndex, size_t... BIndex>
1925
+ void apply_broadcast(std::array<buffer_info, NVectorized> &buffers,
1926
+ std::array<void *, N> &params,
1927
+ Return *out,
1928
+ size_t size,
1929
+ const std::vector<ssize_t> &output_shape,
1930
+ index_sequence<Index...>,
1931
+ index_sequence<VIndex...>,
1932
+ index_sequence<BIndex...>) {
1933
+
1934
+ multi_array_iterator<NVectorized> input_iter(buffers, output_shape);
1935
+
1936
+ for (size_t i = 0; i < size; ++i, ++input_iter) {
1937
+ PYBIND11_EXPAND_SIDE_EFFECTS((params[VIndex] = input_iter.template data<BIndex>()));
1938
+ returned_array::call(
1939
+ out, i, f, *reinterpret_cast<param_n_t<Index> *>(std::get<Index>(params))...);
1940
+ }
1941
+ }
1942
+ };
1943
+
1944
+ template <typename Func, typename Return, typename... Args>
1945
+ vectorize_helper<Func, Return, Args...> vectorize_extractor(const Func &f, Return (*)(Args...)) {
1946
+ return detail::vectorize_helper<Func, Return, Args...>(f);
1947
+ }
1948
+
1949
+ template <typename T, int Flags>
1950
+ struct handle_type_name<array_t<T, Flags>> {
1951
+ static constexpr auto name
1952
+ = const_name("numpy.ndarray[") + npy_format_descriptor<T>::name + const_name("]");
1953
+ };
1954
+
1955
+ PYBIND11_NAMESPACE_END(detail)
1956
+
1957
+ // Vanilla pointer vectorizer:
1958
+ template <typename Return, typename... Args>
1959
+ detail::vectorize_helper<Return (*)(Args...), Return, Args...> vectorize(Return (*f)(Args...)) {
1960
+ return detail::vectorize_helper<Return (*)(Args...), Return, Args...>(f);
1961
+ }
1962
+
1963
+ // lambda vectorizer:
1964
+ template <typename Func, detail::enable_if_t<detail::is_lambda<Func>::value, int> = 0>
1965
+ auto vectorize(Func &&f)
1966
+ -> decltype(detail::vectorize_extractor(std::forward<Func>(f),
1967
+ (detail::function_signature_t<Func> *) nullptr)) {
1968
+ return detail::vectorize_extractor(std::forward<Func>(f),
1969
+ (detail::function_signature_t<Func> *) nullptr);
1970
+ }
1971
+
1972
+ // Vectorize a class method (non-const):
1973
+ template <typename Return,
1974
+ typename Class,
1975
+ typename... Args,
1976
+ typename Helper = detail::vectorize_helper<
1977
+ decltype(std::mem_fn(std::declval<Return (Class::*)(Args...)>())),
1978
+ Return,
1979
+ Class *,
1980
+ Args...>>
1981
+ Helper vectorize(Return (Class::*f)(Args...)) {
1982
+ return Helper(std::mem_fn(f));
1983
+ }
1984
+
1985
+ // Vectorize a class method (const):
1986
+ template <typename Return,
1987
+ typename Class,
1988
+ typename... Args,
1989
+ typename Helper = detail::vectorize_helper<
1990
+ decltype(std::mem_fn(std::declval<Return (Class::*)(Args...) const>())),
1991
+ Return,
1992
+ const Class *,
1993
+ Args...>>
1994
+ Helper vectorize(Return (Class::*f)(Args...) const) {
1995
+ return Helper(std::mem_fn(f));
1996
+ }
1997
+
1998
+ PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)