nvfuser-cu121-torch25 0.2.25.dev20250201__cp312-cp312-manylinux_2_28_x86_64.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (242) hide show
  1. nvfuser/_C.cpython-312-x86_64-linux-gnu.so +0 -0
  2. nvfuser/__init__.py +618 -0
  3. nvfuser/__init__.pyi +4 -0
  4. nvfuser/contrib/__init__.py +9 -0
  5. nvfuser/contrib/nn/__init__.py +13 -0
  6. nvfuser/contrib/nn/normalization.py +725 -0
  7. nvfuser/include/nvfuser/alias_analysis.h +116 -0
  8. nvfuser/include/nvfuser/bfs.h +929 -0
  9. nvfuser/include/nvfuser/codegen.h +26 -0
  10. nvfuser/include/nvfuser/compute_at.h +28 -0
  11. nvfuser/include/nvfuser/compute_at_map.h +394 -0
  12. nvfuser/include/nvfuser/contiguity.h +351 -0
  13. nvfuser/include/nvfuser/cuda_utils.h +50 -0
  14. nvfuser/include/nvfuser/debug.h +50 -0
  15. nvfuser/include/nvfuser/device_lower/analysis/bank_conflict.h +53 -0
  16. nvfuser/include/nvfuser/device_lower/analysis/circular_buffer.h +109 -0
  17. nvfuser/include/nvfuser/device_lower/analysis/device_version.h +65 -0
  18. nvfuser/include/nvfuser/device_lower/analysis/divisible_split.h +28 -0
  19. nvfuser/include/nvfuser/device_lower/analysis/fused_reduction.h +36 -0
  20. nvfuser/include/nvfuser/device_lower/analysis/index_compute.h +322 -0
  21. nvfuser/include/nvfuser/device_lower/analysis/predicate_elimination.h +71 -0
  22. nvfuser/include/nvfuser/device_lower/analysis/sync_information.h +47 -0
  23. nvfuser/include/nvfuser/device_lower/analysis/tensor_memory.h +65 -0
  24. nvfuser/include/nvfuser/device_lower/analysis/thread_predicate.h +158 -0
  25. nvfuser/include/nvfuser/device_lower/analysis/tma.h +93 -0
  26. nvfuser/include/nvfuser/device_lower/analysis/trivial_broadcast.h +75 -0
  27. nvfuser/include/nvfuser/device_lower/id_model_options.h +135 -0
  28. nvfuser/include/nvfuser/device_lower/lower2device.h +391 -0
  29. nvfuser/include/nvfuser/device_lower/pass/alias_memory.h +37 -0
  30. nvfuser/include/nvfuser/device_lower/pass/allocation.h +32 -0
  31. nvfuser/include/nvfuser/device_lower/pass/circular_buffer.h +191 -0
  32. nvfuser/include/nvfuser/device_lower/pass/expr_sort.h +17 -0
  33. nvfuser/include/nvfuser/device_lower/pass/fusion_simplifier.h +21 -0
  34. nvfuser/include/nvfuser/device_lower/pass/grid_serialization.h +26 -0
  35. nvfuser/include/nvfuser/device_lower/pass/index.h +200 -0
  36. nvfuser/include/nvfuser/device_lower/pass/inline_ptx.h +16 -0
  37. nvfuser/include/nvfuser/device_lower/pass/insert_syncs.h +39 -0
  38. nvfuser/include/nvfuser/device_lower/pass/instrument.h +24 -0
  39. nvfuser/include/nvfuser/device_lower/pass/loop_rotation.h +150 -0
  40. nvfuser/include/nvfuser/device_lower/pass/loops.h +68 -0
  41. nvfuser/include/nvfuser/device_lower/pass/magic_zero.h +86 -0
  42. nvfuser/include/nvfuser/device_lower/pass/misaligned_vectorization.h +118 -0
  43. nvfuser/include/nvfuser/device_lower/pass/predicate.h +23 -0
  44. nvfuser/include/nvfuser/device_lower/pass/replace_size.h +24 -0
  45. nvfuser/include/nvfuser/device_lower/pass/scalar_hoist.h +115 -0
  46. nvfuser/include/nvfuser/device_lower/pass/unroll.h +98 -0
  47. nvfuser/include/nvfuser/device_lower/pass/vectorize_welford.h +45 -0
  48. nvfuser/include/nvfuser/device_lower/pass/warp_reduce.h +23 -0
  49. nvfuser/include/nvfuser/device_lower/utils.h +382 -0
  50. nvfuser/include/nvfuser/device_lower/validation.h +74 -0
  51. nvfuser/include/nvfuser/disjoint_set.h +556 -0
  52. nvfuser/include/nvfuser/dispatch.h +334 -0
  53. nvfuser/include/nvfuser/driver_api.h +49 -0
  54. nvfuser/include/nvfuser/dynamic_transform.h +316 -0
  55. nvfuser/include/nvfuser/dynamic_type/C++20/type_traits +37 -0
  56. nvfuser/include/nvfuser/dynamic_type/dynamic_type.h +969 -0
  57. nvfuser/include/nvfuser/dynamic_type/error.h +24 -0
  58. nvfuser/include/nvfuser/dynamic_type/type_traits.h +703 -0
  59. nvfuser/include/nvfuser/evaluator_common.h +295 -0
  60. nvfuser/include/nvfuser/exceptions.h +283 -0
  61. nvfuser/include/nvfuser/expr_evaluator.h +125 -0
  62. nvfuser/include/nvfuser/expr_simplifier.h +218 -0
  63. nvfuser/include/nvfuser/flatbuffers/allocator.h +68 -0
  64. nvfuser/include/nvfuser/flatbuffers/array.h +253 -0
  65. nvfuser/include/nvfuser/flatbuffers/base.h +486 -0
  66. nvfuser/include/nvfuser/flatbuffers/buffer.h +154 -0
  67. nvfuser/include/nvfuser/flatbuffers/buffer_ref.h +53 -0
  68. nvfuser/include/nvfuser/flatbuffers/code_generator.h +80 -0
  69. nvfuser/include/nvfuser/flatbuffers/code_generators.h +234 -0
  70. nvfuser/include/nvfuser/flatbuffers/default_allocator.h +64 -0
  71. nvfuser/include/nvfuser/flatbuffers/detached_buffer.h +114 -0
  72. nvfuser/include/nvfuser/flatbuffers/flatbuffer_builder.h +1225 -0
  73. nvfuser/include/nvfuser/flatbuffers/flatbuffers.h +272 -0
  74. nvfuser/include/nvfuser/flatbuffers/flatc.h +130 -0
  75. nvfuser/include/nvfuser/flatbuffers/flex_flat_util.h +36 -0
  76. nvfuser/include/nvfuser/flatbuffers/flexbuffers.h +1889 -0
  77. nvfuser/include/nvfuser/flatbuffers/grpc.h +300 -0
  78. nvfuser/include/nvfuser/flatbuffers/hash.h +127 -0
  79. nvfuser/include/nvfuser/flatbuffers/idl.h +1359 -0
  80. nvfuser/include/nvfuser/flatbuffers/minireflect.h +420 -0
  81. nvfuser/include/nvfuser/flatbuffers/reflection.h +522 -0
  82. nvfuser/include/nvfuser/flatbuffers/reflection_generated.h +1471 -0
  83. nvfuser/include/nvfuser/flatbuffers/registry.h +128 -0
  84. nvfuser/include/nvfuser/flatbuffers/stl_emulation.h +513 -0
  85. nvfuser/include/nvfuser/flatbuffers/string.h +64 -0
  86. nvfuser/include/nvfuser/flatbuffers/struct.h +53 -0
  87. nvfuser/include/nvfuser/flatbuffers/table.h +168 -0
  88. nvfuser/include/nvfuser/flatbuffers/util.h +731 -0
  89. nvfuser/include/nvfuser/flatbuffers/vector.h +393 -0
  90. nvfuser/include/nvfuser/flatbuffers/vector_downward.h +273 -0
  91. nvfuser/include/nvfuser/flatbuffers/verifier.h +317 -0
  92. nvfuser/include/nvfuser/fusion.h +511 -0
  93. nvfuser/include/nvfuser/fusion_guard.h +37 -0
  94. nvfuser/include/nvfuser/fusion_profiler.h +311 -0
  95. nvfuser/include/nvfuser/fusion_segmenter.h +751 -0
  96. nvfuser/include/nvfuser/global_allocator.h +27 -0
  97. nvfuser/include/nvfuser/grouped_reduction.h +47 -0
  98. nvfuser/include/nvfuser/host_ir/container.h +60 -0
  99. nvfuser/include/nvfuser/host_ir/executor.h +152 -0
  100. nvfuser/include/nvfuser/host_ir/host_ir.h +320 -0
  101. nvfuser/include/nvfuser/host_ir/lower.h +35 -0
  102. nvfuser/include/nvfuser/id_model/circular_buffer_indexing.h +56 -0
  103. nvfuser/include/nvfuser/id_model/contiguity.h +166 -0
  104. nvfuser/include/nvfuser/id_model/id_model.h +359 -0
  105. nvfuser/include/nvfuser/id_model/id_model_index_compute.h +81 -0
  106. nvfuser/include/nvfuser/id_model/indexing.h +208 -0
  107. nvfuser/include/nvfuser/id_model/indexing_traversal.h +72 -0
  108. nvfuser/include/nvfuser/id_model/indexing_utils.h +62 -0
  109. nvfuser/include/nvfuser/id_model/loop_promotion.h +180 -0
  110. nvfuser/include/nvfuser/id_model/predicate_indexing.h +104 -0
  111. nvfuser/include/nvfuser/id_model/schedule.h +54 -0
  112. nvfuser/include/nvfuser/id_model/to_string.h +87 -0
  113. nvfuser/include/nvfuser/id_model/transform_replay.h +58 -0
  114. nvfuser/include/nvfuser/id_model/utils.h +176 -0
  115. nvfuser/include/nvfuser/id_model/validation_utils.h +55 -0
  116. nvfuser/include/nvfuser/index_compute.h +651 -0
  117. nvfuser/include/nvfuser/instrumentation.h +107 -0
  118. nvfuser/include/nvfuser/ir/all_nodes.h +14 -0
  119. nvfuser/include/nvfuser/ir/base_nodes.h +687 -0
  120. nvfuser/include/nvfuser/ir/builder.h +215 -0
  121. nvfuser/include/nvfuser/ir/builder_passkey.h +29 -0
  122. nvfuser/include/nvfuser/ir/cloner.h +185 -0
  123. nvfuser/include/nvfuser/ir/container.h +226 -0
  124. nvfuser/include/nvfuser/ir/graphviz.h +119 -0
  125. nvfuser/include/nvfuser/ir/interface_nodes.h +957 -0
  126. nvfuser/include/nvfuser/ir/internal_base_nodes.h +744 -0
  127. nvfuser/include/nvfuser/ir/internal_nodes.h +2792 -0
  128. nvfuser/include/nvfuser/ir/iostream.h +98 -0
  129. nvfuser/include/nvfuser/ir/printer.h +57 -0
  130. nvfuser/include/nvfuser/ir/utils.h +801 -0
  131. nvfuser/include/nvfuser/iter_visitor.h +661 -0
  132. nvfuser/include/nvfuser/kernel.h +299 -0
  133. nvfuser/include/nvfuser/kernel_db/kernel_db.h +109 -0
  134. nvfuser/include/nvfuser/kernel_db/utils.h +37 -0
  135. nvfuser/include/nvfuser/kernel_ir.h +1457 -0
  136. nvfuser/include/nvfuser/kernel_ir_dispatch.h +147 -0
  137. nvfuser/include/nvfuser/linked_hash_map.h +97 -0
  138. nvfuser/include/nvfuser/logical_domain_map.h +577 -0
  139. nvfuser/include/nvfuser/macros.h +23 -0
  140. nvfuser/include/nvfuser/mma_type.h +257 -0
  141. nvfuser/include/nvfuser/multidevice/c10d_mock.h +175 -0
  142. nvfuser/include/nvfuser/multidevice/communication.h +232 -0
  143. nvfuser/include/nvfuser/multidevice/communicator.h +179 -0
  144. nvfuser/include/nvfuser/multidevice/device_mesh.h +95 -0
  145. nvfuser/include/nvfuser/multidevice/executor.h +107 -0
  146. nvfuser/include/nvfuser/multidevice/multidevice.h +18 -0
  147. nvfuser/include/nvfuser/multidevice/utils.h +187 -0
  148. nvfuser/include/nvfuser/non_divisible_split.h +86 -0
  149. nvfuser/include/nvfuser/opaque_type.h +129 -0
  150. nvfuser/include/nvfuser/ops/alias.h +192 -0
  151. nvfuser/include/nvfuser/ops/all_ops.h +13 -0
  152. nvfuser/include/nvfuser/ops/arith.h +712 -0
  153. nvfuser/include/nvfuser/ops/composite.h +130 -0
  154. nvfuser/include/nvfuser/ops/indexing.h +55 -0
  155. nvfuser/include/nvfuser/ops/normalization.h +263 -0
  156. nvfuser/include/nvfuser/ops/utils.h +127 -0
  157. nvfuser/include/nvfuser/options.h +313 -0
  158. nvfuser/include/nvfuser/parallel_dimension_map.h +95 -0
  159. nvfuser/include/nvfuser/parallel_type_bitmap.h +365 -0
  160. nvfuser/include/nvfuser/polymorphic_value.h +432 -0
  161. nvfuser/include/nvfuser/predicate_compute.h +213 -0
  162. nvfuser/include/nvfuser/python_frontend/distributed_tensor.h +50 -0
  163. nvfuser/include/nvfuser/python_frontend/fusion_cache.h +298 -0
  164. nvfuser/include/nvfuser/python_frontend/fusion_definition.h +372 -0
  165. nvfuser/include/nvfuser/python_frontend/fusion_record.h +3124 -0
  166. nvfuser/include/nvfuser/python_frontend/fusion_state.h +143 -0
  167. nvfuser/include/nvfuser/python_frontend/python_bindings.h +27 -0
  168. nvfuser/include/nvfuser/python_frontend/segmentation.h +246 -0
  169. nvfuser/include/nvfuser/python_frontend/translation.h +20 -0
  170. nvfuser/include/nvfuser/python_frontend/translation_utils.h +308 -0
  171. nvfuser/include/nvfuser/scheduler/all_schedulers.h +17 -0
  172. nvfuser/include/nvfuser/scheduler/ampere_multi_matmul.h +206 -0
  173. nvfuser/include/nvfuser/scheduler/cache_policy_refiner.h +19 -0
  174. nvfuser/include/nvfuser/scheduler/compile_time_info.h +322 -0
  175. nvfuser/include/nvfuser/scheduler/debug_utils.h +68 -0
  176. nvfuser/include/nvfuser/scheduler/expr_eval_sched.h +45 -0
  177. nvfuser/include/nvfuser/scheduler/heuristic.h +113 -0
  178. nvfuser/include/nvfuser/scheduler/hopper_multi_matmul.h +204 -0
  179. nvfuser/include/nvfuser/scheduler/mark_aliases.h +19 -0
  180. nvfuser/include/nvfuser/scheduler/matmul.h +40 -0
  181. nvfuser/include/nvfuser/scheduler/matmul_heuristic.h +293 -0
  182. nvfuser/include/nvfuser/scheduler/matmul_heuristic_plugin.h +65 -0
  183. nvfuser/include/nvfuser/scheduler/matmul_heuristic_plugin_api.h +99 -0
  184. nvfuser/include/nvfuser/scheduler/matmul_utils.h +54 -0
  185. nvfuser/include/nvfuser/scheduler/mma_utils.h +500 -0
  186. nvfuser/include/nvfuser/scheduler/multi_matmul.h +74 -0
  187. nvfuser/include/nvfuser/scheduler/no_op.h +48 -0
  188. nvfuser/include/nvfuser/scheduler/normalization_inner.h +49 -0
  189. nvfuser/include/nvfuser/scheduler/normalization_inner_outer.h +51 -0
  190. nvfuser/include/nvfuser/scheduler/normalization_outer.h +48 -0
  191. nvfuser/include/nvfuser/scheduler/normalization_utils.h +379 -0
  192. nvfuser/include/nvfuser/scheduler/pointwise.h +183 -0
  193. nvfuser/include/nvfuser/scheduler/pointwise_heuristic.h +118 -0
  194. nvfuser/include/nvfuser/scheduler/pointwise_utils.h +24 -0
  195. nvfuser/include/nvfuser/scheduler/reduction.h +43 -0
  196. nvfuser/include/nvfuser/scheduler/reduction_heuristic.h +339 -0
  197. nvfuser/include/nvfuser/scheduler/reduction_utils.h +159 -0
  198. nvfuser/include/nvfuser/scheduler/registry.h +97 -0
  199. nvfuser/include/nvfuser/scheduler/registry_utils.h +111 -0
  200. nvfuser/include/nvfuser/scheduler/resize.h +41 -0
  201. nvfuser/include/nvfuser/scheduler/resize_heuristic.h +67 -0
  202. nvfuser/include/nvfuser/scheduler/runtime_info.h +166 -0
  203. nvfuser/include/nvfuser/scheduler/scheduler_types.h +80 -0
  204. nvfuser/include/nvfuser/scheduler/transpose.h +114 -0
  205. nvfuser/include/nvfuser/scheduler/transpose_heuristic.h +164 -0
  206. nvfuser/include/nvfuser/scheduler/utils.h +771 -0
  207. nvfuser/include/nvfuser/scheduler/vectorize_helper.h +349 -0
  208. nvfuser/include/nvfuser/serde/factory.h +55 -0
  209. nvfuser/include/nvfuser/serde/fusion_cache_generated.h +4319 -0
  210. nvfuser/include/nvfuser/serde/fusion_record.h +124 -0
  211. nvfuser/include/nvfuser/serde/polymorphic_value.h +52 -0
  212. nvfuser/include/nvfuser/serde/utils.h +34 -0
  213. nvfuser/include/nvfuser/struct.inl +127 -0
  214. nvfuser/include/nvfuser/swizzle.h +54 -0
  215. nvfuser/include/nvfuser/sys_utils.h +40 -0
  216. nvfuser/include/nvfuser/tensor_metadata.h +118 -0
  217. nvfuser/include/nvfuser/tma.h +124 -0
  218. nvfuser/include/nvfuser/transform_iter.h +522 -0
  219. nvfuser/include/nvfuser/transform_replay.h +297 -0
  220. nvfuser/include/nvfuser/transform_rfactor.h +33 -0
  221. nvfuser/include/nvfuser/transform_view.h +136 -0
  222. nvfuser/include/nvfuser/type.h +1125 -0
  223. nvfuser/include/nvfuser/type_promotion.h +61 -0
  224. nvfuser/include/nvfuser/utils.h +619 -0
  225. nvfuser/include/nvfuser/val_graph.h +446 -0
  226. nvfuser/include/nvfuser/val_graph_visitor.h +259 -0
  227. nvfuser/include/nvfuser/validator_utils.h +92 -0
  228. nvfuser/include/nvfuser/vectorization_info.h +31 -0
  229. nvfuser/include/nvfuser/visibility.h +21 -0
  230. nvfuser/lib/libnvfuser_codegen.so +0 -0
  231. nvfuser/nvfuser_version.py +69 -0
  232. nvfuser/pytorch_utils.py +184 -0
  233. nvfuser/share/cmake/nvfuser/NvfuserConfig-release.cmake +20 -0
  234. nvfuser/share/cmake/nvfuser/NvfuserConfig.cmake +106 -0
  235. nvfuser/utils.py +18 -0
  236. nvfuser/version.py +1 -0
  237. nvfuser_cu121_torch25-0.2.25.dev20250201.dist-info/LICENSE +976 -0
  238. nvfuser_cu121_torch25-0.2.25.dev20250201.dist-info/METADATA +16 -0
  239. nvfuser_cu121_torch25-0.2.25.dev20250201.dist-info/RECORD +242 -0
  240. nvfuser_cu121_torch25-0.2.25.dev20250201.dist-info/WHEEL +5 -0
  241. nvfuser_cu121_torch25-0.2.25.dev20250201.dist-info/top_level.txt +1 -0
  242. nvfuser_cu121_torch25.libs/libnvToolsExt-847d78f2.so.1.0.0 +0 -0
@@ -0,0 +1,703 @@
1
+ // clang-format off
2
+ /*
3
+ * SPDX-FileCopyrightText: Copyright (c) 2023-present NVIDIA CORPORATION & AFFILIATES.
4
+ * All rights reserved.
5
+ * SPDX-License-Identifier: BSD-3-Clause
6
+ */
7
+ // clang-format on
8
+ #pragma once
9
+
10
+ #include <tuple>
11
+ #include <type_traits>
12
+ #include <utility>
13
+
14
+ #include "C++20/type_traits"
15
+
16
+ // Note on the coding style of this file:
17
+ // - I use `namespace dynamic_type` and `} // namespace dynamic_type` a lot to
18
+ // separate different parts of the code, so that we can easily fold and unfold
19
+ // them in editors that support folding.
20
+ // - Many tests are done with static_assert, so I just put it here, instead of
21
+ // writing a separate test file. Because I think these tests serves as a good
22
+ // documentation of the usage.
23
+
24
+ // Important priliminary knowledge to understand this file:
25
+ // Starting from C++14, lambdas can have auto in its parameter list, for
26
+ // example:
27
+ // auto f = [](auto x) { return -x; };
28
+ // on C++17, we can be even crazier:
29
+ // auto f = [](auto x) {
30
+ // if constexpr (std::is_same_v<decltype(x), int>) {
31
+ // return -x;
32
+ // } else {
33
+ // // The return type can be very different for different types of x
34
+ // return;
35
+ // }
36
+ // };
37
+ // I find it helpful to understand this feature by considering the auto lambda
38
+ // as something like this:
39
+ // struct Lambda {
40
+ // template <typename T>
41
+ // auto operator()(T x) {
42
+ // ...
43
+ // }
44
+ // };
45
+
46
+ namespace dynamic_type {
47
+
48
+ // Implementation detail
49
+ namespace can_use_args_impl {
50
+
51
+ // For how to use std::void_t for SFINAE, see
52
+ // https://en.cppreference.com/w/cpp/types/void_t
53
+
54
+ template <typename, typename Fun, typename... Ts>
55
+ struct CanUseArg : std::false_type {};
56
+
57
+ template <typename Fun, typename... Ts>
58
+ struct CanUseArg<
59
+ std::void_t<decltype(std::declval<Fun>()(std::declval<Ts>()...))>,
60
+ Fun,
61
+ Ts...> : std::true_type {};
62
+
63
+ } // namespace can_use_args_impl
64
+
65
+ // Check if a function Fun can be called with arguments Ts...
66
+
67
+ template <typename Fun, typename... Ts>
68
+ constexpr bool can_use_args =
69
+ can_use_args_impl::CanUseArg<void, Fun, Ts...>::value;
70
+
71
+ // For example, `float sin(float)` can be called with int, but not with float*
72
+ // so:
73
+ static_assert(can_use_args<float (*)(float), int>);
74
+ static_assert(!can_use_args<float (*)(float), float*>);
75
+
76
+ } // namespace dynamic_type
77
+
78
+ namespace dynamic_type {
79
+
80
+ // Implementation detail for opcheck. This implementation is very long, I
81
+ // recommend read the usage doc below first before reading this implementation.
82
+ namespace opcheck_impl {
83
+
84
+ // A type that is purposely made implicitly convertible from OperatorChecker
85
+ struct CastableFromOperatorChecker {};
86
+
87
+ template <typename T, typename = void>
88
+ struct HasArrowOperator : std::false_type {};
89
+
90
+ template <typename T>
91
+ struct HasArrowOperator<
92
+ T,
93
+ std::void_t<decltype(std::declval<decltype(&T::operator->)>())>>
94
+ : std::true_type {};
95
+
96
+ template <typename From, typename To, typename = void>
97
+ struct HasExplicitConversion : std::false_type {};
98
+
99
+ template <typename From, typename To>
100
+ struct HasExplicitConversion<
101
+ From,
102
+ To,
103
+ std::void_t<decltype(std::declval<decltype(&From::operator To)>())>>
104
+ : std::true_type {};
105
+
106
+ struct TrueType {
107
+ static constexpr bool value() {
108
+ return true;
109
+ }
110
+ };
111
+
112
+ struct FalseType {
113
+ static constexpr bool value() {
114
+ return false;
115
+ }
116
+ };
117
+
118
+ template <typename T>
119
+ struct OperatorChecker {
120
+ constexpr operator CastableFromOperatorChecker() const {
121
+ return {};
122
+ }
123
+
124
+ // The trick here is, when the compiler sees `operator=`, It will first try
125
+ // with the function signature that does not require implicit conversion, that
126
+ // is, the first candidate. And only if the first candidate fails to match, it
127
+ // will try the function signatures that requires implicit conversion from
128
+ // OperatorChecker to CastableFromOperatorChecker. In the code below, if the
129
+ // expression (std::declval<T>() = std::declval<T1>()) is well-formed, then
130
+ // template deduction for the first candidate will succeed, so it will be
131
+ // chosen. If not, then the compiler will find that the second candidate is
132
+ // also a match by casting OperatorChecker to CastableFromOperatorChecker.
133
+ // So the second candidate will be chosen.
134
+
135
+ // NOLINTBEGIN(cppcoreguidelines-c-copy-assignment-signature)
136
+ template <typename T1>
137
+ constexpr auto operator=(OperatorChecker<T1>) const
138
+ -> decltype((std::declval<T>() = std::declval<T1>()), true) {
139
+ return true;
140
+ }
141
+ constexpr bool operator=(CastableFromOperatorChecker) const {
142
+ return false;
143
+ }
144
+ // NOLINTEND(cppcoreguidelines-c-copy-assignment-signature)
145
+
146
+ template <
147
+ typename T1 = int,
148
+ typename... Ts,
149
+ std::enable_if_t<can_use_args<T, Ts...>, T1> = 0>
150
+ constexpr bool operator()(OperatorChecker<Ts>... args) const {
151
+ return true;
152
+ }
153
+ template <
154
+ typename T1 = int,
155
+ typename... Ts,
156
+ std::enable_if_t<!can_use_args<T, Ts...>, T1> = 0>
157
+ constexpr bool operator()(OperatorChecker<Ts>... args) const {
158
+ return false;
159
+ }
160
+
161
+ template <typename T1>
162
+ constexpr auto operator[](OperatorChecker<T1>) const
163
+ -> decltype((std::declval<T>()[std::declval<T1>()]), true) {
164
+ return true;
165
+ }
166
+ constexpr bool operator[](CastableFromOperatorChecker) const {
167
+ return false;
168
+ }
169
+
170
+ template <
171
+ typename T1 = int,
172
+ std::enable_if_t<HasArrowOperator<T>::value, T1> = 0>
173
+ constexpr auto operator->() const -> TrueType* {
174
+ return nullptr;
175
+ }
176
+ template <
177
+ typename T1 = int,
178
+ std::enable_if_t<!HasArrowOperator<T>::value, T1> = 0>
179
+ constexpr auto operator->() const -> FalseType* {
180
+ return nullptr;
181
+ }
182
+
183
+ template <typename T1>
184
+ constexpr auto operator->*(OperatorChecker<T1>) const
185
+ -> decltype((std::declval<T>()->*std::declval<T1>()), true) {
186
+ return true;
187
+ }
188
+ constexpr bool operator->*(CastableFromOperatorChecker) const {
189
+ return false;
190
+ }
191
+
192
+ template <typename T1>
193
+ constexpr auto canCastTo(OperatorChecker<T1>) const
194
+ -> decltype(((T1)(std::declval<T>())), true) {
195
+ return true;
196
+ }
197
+ constexpr bool canCastTo(CastableFromOperatorChecker) const {
198
+ return false;
199
+ }
200
+
201
+ template <
202
+ typename T1,
203
+ typename = std::enable_if_t<HasExplicitConversion<T, T1>::value>>
204
+ constexpr bool hasExplicitCastTo(OperatorChecker<T1>) const {
205
+ return true;
206
+ }
207
+ constexpr bool hasExplicitCastTo(CastableFromOperatorChecker) const {
208
+ return false;
209
+ }
210
+ };
211
+
212
+ #define DEFINE_UNARY_OP(op) \
213
+ template <typename T1> \
214
+ constexpr auto operator op(OperatorChecker<T1>) \
215
+ ->decltype(op std::declval<T1>(), true) { \
216
+ return true; \
217
+ } \
218
+ \
219
+ constexpr bool operator op(CastableFromOperatorChecker) { \
220
+ return false; \
221
+ }
222
+
223
+ #define DEFINE_UNARY_SUFFIX_OP(op) \
224
+ template <typename T1> \
225
+ constexpr auto operator op(OperatorChecker<T1>, int) \
226
+ ->decltype(std::declval<T1>() op, true) { \
227
+ return true; \
228
+ } \
229
+ \
230
+ constexpr bool operator op(CastableFromOperatorChecker, int) { \
231
+ return false; \
232
+ }
233
+
234
+ #define DEFINE_BINARY_OP(op) \
235
+ template <typename T1, typename T2> \
236
+ constexpr auto operator op(OperatorChecker<T1>, OperatorChecker<T2>) \
237
+ ->decltype((std::declval<T1>() op std::declval<T2>()), true) { \
238
+ return true; \
239
+ } \
240
+ \
241
+ constexpr bool operator op( \
242
+ CastableFromOperatorChecker, CastableFromOperatorChecker) { \
243
+ return false; \
244
+ }
245
+
246
+ // Unary operators
247
+ DEFINE_UNARY_OP(+);
248
+ DEFINE_UNARY_OP(-);
249
+ DEFINE_UNARY_OP(~);
250
+ DEFINE_UNARY_OP(!);
251
+ DEFINE_UNARY_OP(++);
252
+ DEFINE_UNARY_OP(--);
253
+ DEFINE_UNARY_SUFFIX_OP(++);
254
+ DEFINE_UNARY_SUFFIX_OP(--);
255
+ DEFINE_UNARY_OP(*);
256
+ DEFINE_UNARY_OP(&);
257
+
258
+ // Binary operators
259
+ DEFINE_BINARY_OP(+);
260
+ DEFINE_BINARY_OP(-);
261
+ DEFINE_BINARY_OP(*);
262
+ DEFINE_BINARY_OP(/);
263
+ DEFINE_BINARY_OP(%);
264
+ DEFINE_BINARY_OP(&);
265
+ DEFINE_BINARY_OP(|);
266
+ DEFINE_BINARY_OP(^);
267
+ DEFINE_BINARY_OP(&&);
268
+ DEFINE_BINARY_OP(||);
269
+ DEFINE_BINARY_OP(<<);
270
+ DEFINE_BINARY_OP(>>);
271
+ DEFINE_BINARY_OP(==);
272
+ DEFINE_BINARY_OP(!=);
273
+ DEFINE_BINARY_OP(<);
274
+ DEFINE_BINARY_OP(>);
275
+ DEFINE_BINARY_OP(<=);
276
+ DEFINE_BINARY_OP(>=);
277
+
278
+ // Assignment operators
279
+ DEFINE_BINARY_OP(+=);
280
+ DEFINE_BINARY_OP(-=);
281
+ DEFINE_BINARY_OP(*=);
282
+ DEFINE_BINARY_OP(/=);
283
+ DEFINE_BINARY_OP(%=);
284
+ DEFINE_BINARY_OP(&=);
285
+ DEFINE_BINARY_OP(|=);
286
+ DEFINE_BINARY_OP(^=);
287
+ DEFINE_BINARY_OP(<<=);
288
+ DEFINE_BINARY_OP(>>=);
289
+
290
+ #undef DEFINE_UNARY_OP
291
+ #undef DEFINE_UNARY_SUFFIX_OP
292
+ #undef DEFINE_BINARY_OP
293
+
294
+ // comma operator
295
+ // This is essentailly just DEFINE_BINARY_OP(,); But because of the C++
296
+ // preprocessor, comma is treated as a separator for arguments, so we need to do
297
+ // it manually.
298
+ template <typename T1, typename T2>
299
+ constexpr auto operator,(OperatorChecker<T1>, OperatorChecker<T2>)
300
+ -> decltype((std::declval<T1>(), std::declval<T2>()), true) {
301
+ return true;
302
+ }
303
+
304
+ constexpr bool operator,(
305
+ CastableFromOperatorChecker,
306
+ CastableFromOperatorChecker) {
307
+ return false;
308
+ }
309
+
310
+ // TODO: overload the following operators:
311
+ // <=> (requires C++20)
312
+
313
+ } // namespace opcheck_impl
314
+
315
+ // Note [Operator checker]
316
+ //
317
+ // "opcheck" is a utility to check if an operator for certain type is defined.
318
+ template <typename T>
319
+ constexpr opcheck_impl::OperatorChecker<T> opcheck;
320
+
321
+ // For example, if you want to check if int > float is defined, you can do:
322
+ static_assert(opcheck<int> > opcheck<float>);
323
+ // This will be true because int > float is defined. However, if you do
324
+ static_assert(!(opcheck<int> > opcheck<std::pair<int, int>>));
325
+ // This will be false because int > pair is not defined.
326
+ //
327
+ // This utility works for all overloadable operators in C++. Just use these ops
328
+ // on opcheck and you will know if it is defined for the underlying type.
329
+ //
330
+ // Note that the operators on opcheck might behave differently from normal C++.
331
+ // For example, if you assign one opcheck to another opcheck, it will return a
332
+ // bool telling you whether this asignment is valid for the underlying type,
333
+ // instead of actually doing the assignment and return a reference of the lhs
334
+ // opcheck.
335
+ //
336
+ // Due to the limitiation of C++'s operator overloading, some operators'
337
+ // interface might not be as clean as others. For example, the arrow operator ->
338
+ // is a special one. If you want to check if int has ->, you need to do:
339
+ static_assert(!(opcheck<int>->value()));
340
+ //
341
+ // For more examples, see test/opcheck.cpp namespace opcheck_tests
342
+ //
343
+ // Reference about operator overloading:
344
+ // https://en.cppreference.com/w/cpp/language/operators
345
+
346
+ } // namespace dynamic_type
347
+
348
+ namespace dynamic_type {
349
+
350
+ // Basically just "void". We need this because if we have something like
351
+ // std::tuple<void, int> we will be unable to create an instance of it.
352
+ // So we have to use something like std::tuple<Void, int> instead.
353
+ struct Void {};
354
+
355
+ // Run the given function on each type in the variadic template list.
356
+ // The function should take a single argument of type T*. Note that the argument
357
+ // of the function should only be used for type deduction, and its value should
358
+ // not be used.
359
+ //
360
+ // The returned value of the function is a tuple of the return values of the
361
+ // function calls, with void replaced by Void.
362
+ //
363
+ // For example, if you want to print 0.2 as bool, int, and float, you can do the
364
+ // following:
365
+ // auto f = [](auto x) {
366
+ // using T = typename decltype(x)::type;
367
+ // std::cout << T(0.2) << std::endl;
368
+ // };
369
+ // ForAllTypes<bool, int, float>{}(f);
370
+ // And the output will be:
371
+ // 1
372
+ // 0
373
+ // 0.2
374
+
375
+ template <typename... Ts>
376
+ struct ForAllTypes;
377
+
378
+ template <typename T, typename... Ts>
379
+ struct ForAllTypes<T, Ts...> {
380
+ template <typename Fun>
381
+ constexpr auto operator()(Fun f) const {
382
+ using RetT = decltype(f(std::type_identity<T>{}));
383
+ if constexpr (std::is_void_v<RetT>) {
384
+ f(std::type_identity<T>{});
385
+ return std::tuple_cat(std::tuple<Void>{}, ForAllTypes<Ts...>{}(f));
386
+ } else {
387
+ return std::tuple_cat(
388
+ std::make_tuple(f(std::type_identity<T>{})), ForAllTypes<Ts...>{}(f));
389
+ }
390
+ }
391
+ };
392
+
393
+ template <>
394
+ struct ForAllTypes<> {
395
+ template <typename Fun>
396
+ constexpr auto operator()(Fun f) const {
397
+ return std::tuple<>{};
398
+ }
399
+ };
400
+
401
+ } // namespace dynamic_type
402
+
403
+ namespace dynamic_type {
404
+
405
+ // Check if all the booleans in the arguments are true. There are two versions:
406
+ // one for variadic arguments, and one for std::tuple.
407
+
408
+ template <typename... Ts>
409
+ constexpr bool all(Ts... bs) {
410
+ return (bs && ...);
411
+ }
412
+
413
+ template <typename... Ts>
414
+ constexpr bool all(std::tuple<Ts...> bs) {
415
+ return std::apply([](auto... bs) { return all(bs...); }, bs);
416
+ }
417
+
418
+ // For example:
419
+ static_assert(all(true, true, true));
420
+ static_assert(all(std::make_tuple(true, true, true)));
421
+ static_assert(!all(true, false, true));
422
+ static_assert(!all(std::make_tuple(true, false, true)));
423
+
424
+ } // namespace dynamic_type
425
+
426
+ namespace dynamic_type {
427
+
428
+ // Check if all the booleans in the arguments are true. There are two versions:
429
+ // one for variadic arguments, and one for std::tuple.
430
+
431
+ template <typename... Ts>
432
+ constexpr bool any(Ts... bs) {
433
+ return (bs || ...);
434
+ }
435
+
436
+ template <typename... Ts>
437
+ constexpr bool any(std::tuple<Ts...> bs) {
438
+ return std::apply([](auto... bs) { return any(bs...); }, bs);
439
+ }
440
+
441
+ // For example:
442
+ static_assert(any(true, true, true));
443
+ static_assert(any(std::make_tuple(true, true, true)));
444
+ static_assert(any(true, false, true));
445
+ static_assert(any(std::make_tuple(true, false, true)));
446
+ static_assert(!any(false, false, false));
447
+ static_assert(!any(std::make_tuple(false, false, false)));
448
+
449
+ } // namespace dynamic_type
450
+
451
+ namespace dynamic_type {
452
+
453
+ // Remove all the voids from a tuple. For example:
454
+ // (Void, T1, Void, T2, Void, T3, ...) -> (T1, T2, T3, ...)
455
+
456
+ template <typename... Ts>
457
+ constexpr auto remove_void_from_tuple([[maybe_unused]] std::tuple<Ts...> t) {
458
+ if constexpr (sizeof...(Ts) == 0) {
459
+ return std::tuple<>{};
460
+ } else {
461
+ auto [head, others] = std::apply(
462
+ [](auto head, auto... tail) {
463
+ return std::make_tuple(
464
+ std::make_tuple(head), std::make_tuple(tail...));
465
+ },
466
+ t);
467
+ auto proccessed_others = remove_void_from_tuple(others);
468
+ if constexpr (std::is_same_v<
469
+ std::tuple_element_t<0, decltype(head)>,
470
+ Void>) {
471
+ return proccessed_others;
472
+ } else {
473
+ return std::tuple_cat(head, proccessed_others);
474
+ }
475
+ }
476
+ }
477
+
478
+ // For example:
479
+ static_assert(
480
+ remove_void_from_tuple(
481
+ std::make_tuple(Void{}, 1, Void{}, true, Void{}, 3.5, Void{})) ==
482
+ std::make_tuple(1, true, 3.5));
483
+
484
+ } // namespace dynamic_type
485
+
486
+ namespace dynamic_type {
487
+
488
+ namespace belongs_to_impl {
489
+
490
+ // Given a tuple of Ts, return a tuple with the same size as Ts. The tuple
491
+ // contains either true or void. (true if T is the same as the corresponding
492
+ // type in Ts, void otherwise). For example, if T = int, Ts is (int, float,
493
+ // bool), then the return type is (true, void, void).
494
+ template <typename T, typename... Ts>
495
+ auto get_match_tuple() {
496
+ auto true_or_void = [](auto x) {
497
+ using U = typename decltype(x)::type;
498
+ if constexpr (std::is_same_v<T, U>) {
499
+ return true;
500
+ } else {
501
+ return;
502
+ }
503
+ };
504
+ return ForAllTypes<Ts...>{}(true_or_void);
505
+ }
506
+
507
+ } // namespace belongs_to_impl
508
+
509
+ // Check if T belongs to the given type list Ts. For example
510
+ // belongs_to<int, int, float, bool> is true, but
511
+ // belongs_to<int, float, bool> is false.
512
+ template <typename T, typename... Ts>
513
+ constexpr bool belongs_to =
514
+ (std::tuple_size_v<decltype(remove_void_from_tuple(
515
+ belongs_to_impl::get_match_tuple<T, Ts...>()))> > 0);
516
+
517
+ // For example:
518
+
519
+ static_assert(belongs_to<int, float, double, int>);
520
+ static_assert(!belongs_to<int, float, double, long>);
521
+
522
+ } // namespace dynamic_type
523
+
524
+ namespace dynamic_type {
525
+
526
+ // Take the cartesion product of two tuples.
527
+ // For example:
528
+ // cartesian_product((1, 2), (3, 4)) = ((1, 3), (1, 4), (2, 3), (2, 4))
529
+ template <typename Tuple>
530
+ constexpr auto cartesian_product(Tuple t) {
531
+ return std::apply(
532
+ [](auto... ts) constexpr {
533
+ return std::make_tuple(std::make_tuple(ts)...);
534
+ },
535
+ t);
536
+ }
537
+
538
+ template <typename Tuple1, typename... OtherTuples>
539
+ constexpr auto cartesian_product(Tuple1 first, OtherTuples... others) {
540
+ auto c_first = cartesian_product(first);
541
+ auto c_others = cartesian_product(others...);
542
+ // cat one item in c_first with all the items in c_others
543
+ auto cat_one_first_all_others = [c_others](auto first_item) {
544
+ return std::apply(
545
+ [first_item](auto... other_item) constexpr {
546
+ return std::make_tuple(std::tuple_cat(first_item, other_item)...);
547
+ },
548
+ c_others);
549
+ };
550
+ return std::apply(
551
+ [cat_one_first_all_others](auto... first_items) constexpr {
552
+ return std::tuple_cat(cat_one_first_all_others(first_items)...);
553
+ },
554
+ c_first);
555
+ }
556
+
557
+ // For example:
558
+
559
+ static_assert(
560
+ cartesian_product(std::make_tuple(1.0, true)) ==
561
+ std::make_tuple(std::make_tuple(1.0), std::make_tuple(true)));
562
+
563
+ static_assert(
564
+ cartesian_product(std::make_tuple(1.0, true), std::make_tuple(2.0f, 4)) ==
565
+ std::make_tuple(
566
+ std::make_tuple(1.0, 2.0f),
567
+ std::make_tuple(1.0, 4),
568
+ std::make_tuple(true, 2.0f),
569
+ std::make_tuple(true, 4)));
570
+
571
+ static_assert(
572
+ cartesian_product(
573
+ std::make_tuple(1.0, true),
574
+ std::make_tuple(2.0f, 4),
575
+ std::make_tuple(std::size_t(0), nullptr)) ==
576
+ std::make_tuple(
577
+ std::make_tuple(1.0, 2.0f, std::size_t(0)),
578
+ std::make_tuple(1.0, 2.0f, nullptr),
579
+ std::make_tuple(1.0, 4, std::size_t(0)),
580
+ std::make_tuple(1.0, 4, nullptr),
581
+ std::make_tuple(true, 2.0f, std::size_t(0)),
582
+ std::make_tuple(true, 2.0f, nullptr),
583
+ std::make_tuple(true, 4, std::size_t(0)),
584
+ std::make_tuple(true, 4, nullptr)));
585
+
586
+ } // namespace dynamic_type
587
+
588
+ namespace dynamic_type {
589
+
590
+ // Can I find an x from tuple1 and a y from tuple12 such that f(x, y) is
591
+ // true? f(x, y) must be defined for all x in tuple1 and y in tuple2.
592
+ template <typename... Tuples, typename Fun>
593
+ constexpr bool any_check(Fun f, Tuples... tuples) {
594
+ auto c = cartesian_product(tuples...);
595
+ return std::apply(
596
+ [f](auto... candidates) constexpr {
597
+ return any(std::apply(f, candidates)...);
598
+ },
599
+ c);
600
+ }
601
+
602
+ // For example:
603
+ static_assert(
604
+ any_check([](auto x) constexpr { return x > 0; }, std::make_tuple(1, -1)));
605
+ static_assert(!any_check(
606
+ [](auto x) constexpr { return x > 0; },
607
+ std::make_tuple(-2, -1)));
608
+
609
+ static_assert(any_check(
610
+ [](auto x, auto y) constexpr { return (x + y) > 0; },
611
+ std::make_tuple(2.0, 1),
612
+ std::make_tuple(-2, -1)));
613
+ static_assert(!any_check(
614
+ [](auto x, auto y) constexpr { return (x + y) > 0; },
615
+ std::make_tuple(1.0, 1),
616
+ std::make_tuple(-2, -1)));
617
+
618
+ } // namespace dynamic_type
619
+
620
+ namespace dynamic_type {
621
+
622
+ // Check if all the types in the tuple are the same. If the tuple is empty, or
623
+ // the provided type is not a tuple, then it is considered to be false.
624
+
625
+ template <typename Tuple>
626
+ struct are_all_same : std::false_type {};
627
+
628
+ template <typename T, typename... Rest>
629
+ struct are_all_same<std::tuple<T, Rest...>>
630
+ : std::conjunction<std::is_same<T, Rest>...> {};
631
+
632
+ template <typename T, typename... Rest>
633
+ struct are_all_same<const std::tuple<T, Rest...>>
634
+ : std::conjunction<std::is_same<T, Rest>...> {};
635
+
636
+ template <typename T>
637
+ constexpr bool all_same_type(T) {
638
+ return are_all_same<T>::value;
639
+ }
640
+
641
+ // For example:
642
+ static_assert(are_all_same<std::tuple<int, int, int>>::value);
643
+ static_assert(are_all_same<const std::tuple<int, int, int>>::value);
644
+ static_assert(!are_all_same<std::tuple<int, int, float>>::value);
645
+ static_assert(!are_all_same<std::tuple<>>::value);
646
+
647
+ } // namespace dynamic_type
648
+
649
+ namespace dynamic_type {
650
+
651
+ // Get the first type in a tuple. If the tuple is empty, or the type is not a
652
+ // tuple, then it is considered to be void.
653
+
654
+ template <typename T>
655
+ struct first_or_void {
656
+ using type = void;
657
+ };
658
+
659
+ template <typename T, typename... Ts>
660
+ struct first_or_void<std::tuple<T, Ts...>> {
661
+ using type = T;
662
+ };
663
+
664
+ template <typename T, typename... Ts>
665
+ struct first_or_void<const std::tuple<T, Ts...>> {
666
+ using type = T;
667
+ };
668
+
669
+ // For example:
670
+ static_assert(std::is_same_v<first_or_void<std::tuple<int, float>>::type, int>);
671
+ static_assert(
672
+ std::is_same_v<first_or_void<const std::tuple<int, float>>::type, int>);
673
+ static_assert(std::is_same_v<first_or_void<std::tuple<>>::type, void>);
674
+ static_assert(std::is_same_v<first_or_void<int>::type, void>);
675
+
676
+ } // namespace dynamic_type
677
+
678
+ namespace dynamic_type {
679
+
680
+ // If T is not a reference, then return T, otherwise the wrapped reference type.
681
+
682
+ template <typename T>
683
+ struct wrap_reference {
684
+ using type = T;
685
+ };
686
+
687
+ template <typename T>
688
+ struct wrap_reference<T&> {
689
+ using type = std::reference_wrapper<T>;
690
+ };
691
+
692
+ template <typename T>
693
+ using wrap_reference_t = typename wrap_reference<T>::type;
694
+
695
+ // For example:
696
+ static_assert(std::is_same_v<wrap_reference<int>::type, int>);
697
+ static_assert(
698
+ std::is_same_v<wrap_reference<int&>::type, std::reference_wrapper<int>>);
699
+ static_assert(std::is_same_v<
700
+ wrap_reference<const int&>::type,
701
+ std::reference_wrapper<const int>>);
702
+
703
+ } // namespace dynamic_type