gstaichi 0.1.18.dev1__cp310-cp310-macosx_15_0_arm64.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 (219) hide show
  1. gstaichi-0.1.18.dev1.data/data/include/GLFW/glfw3.h +6389 -0
  2. gstaichi-0.1.18.dev1.data/data/include/GLFW/glfw3native.h +594 -0
  3. gstaichi-0.1.18.dev1.data/data/include/spirv-tools/instrument.hpp +268 -0
  4. gstaichi-0.1.18.dev1.data/data/include/spirv-tools/libspirv.h +907 -0
  5. gstaichi-0.1.18.dev1.data/data/include/spirv-tools/libspirv.hpp +375 -0
  6. gstaichi-0.1.18.dev1.data/data/include/spirv-tools/linker.hpp +97 -0
  7. gstaichi-0.1.18.dev1.data/data/include/spirv-tools/optimizer.hpp +970 -0
  8. gstaichi-0.1.18.dev1.data/data/include/spirv_cross/GLSL.std.450.h +114 -0
  9. gstaichi-0.1.18.dev1.data/data/include/spirv_cross/spirv.h +2568 -0
  10. gstaichi-0.1.18.dev1.data/data/include/spirv_cross/spirv.hpp +2579 -0
  11. gstaichi-0.1.18.dev1.data/data/include/spirv_cross/spirv_cfg.hpp +168 -0
  12. gstaichi-0.1.18.dev1.data/data/include/spirv_cross/spirv_common.hpp +1920 -0
  13. gstaichi-0.1.18.dev1.data/data/include/spirv_cross/spirv_cpp.hpp +93 -0
  14. gstaichi-0.1.18.dev1.data/data/include/spirv_cross/spirv_cross.hpp +1171 -0
  15. gstaichi-0.1.18.dev1.data/data/include/spirv_cross/spirv_cross_c.h +1074 -0
  16. gstaichi-0.1.18.dev1.data/data/include/spirv_cross/spirv_cross_containers.hpp +754 -0
  17. gstaichi-0.1.18.dev1.data/data/include/spirv_cross/spirv_cross_error_handling.hpp +94 -0
  18. gstaichi-0.1.18.dev1.data/data/include/spirv_cross/spirv_cross_parsed_ir.hpp +256 -0
  19. gstaichi-0.1.18.dev1.data/data/include/spirv_cross/spirv_cross_util.hpp +37 -0
  20. gstaichi-0.1.18.dev1.data/data/include/spirv_cross/spirv_glsl.hpp +1001 -0
  21. gstaichi-0.1.18.dev1.data/data/include/spirv_cross/spirv_hlsl.hpp +406 -0
  22. gstaichi-0.1.18.dev1.data/data/include/spirv_cross/spirv_msl.hpp +1273 -0
  23. gstaichi-0.1.18.dev1.data/data/include/spirv_cross/spirv_parser.hpp +103 -0
  24. gstaichi-0.1.18.dev1.data/data/include/spirv_cross/spirv_reflect.hpp +91 -0
  25. gstaichi-0.1.18.dev1.data/data/lib/cmake/SPIRV-Tools/SPIRV-ToolsConfig.cmake +5 -0
  26. gstaichi-0.1.18.dev1.data/data/lib/cmake/SPIRV-Tools/SPIRV-ToolsTarget-release.cmake +29 -0
  27. gstaichi-0.1.18.dev1.data/data/lib/cmake/SPIRV-Tools/SPIRV-ToolsTarget.cmake +114 -0
  28. gstaichi-0.1.18.dev1.data/data/lib/cmake/SPIRV-Tools-diff/SPIRV-Tools-diffConfig.cmake +5 -0
  29. gstaichi-0.1.18.dev1.data/data/lib/cmake/SPIRV-Tools-diff/SPIRV-Tools-diffTargets-release.cmake +19 -0
  30. gstaichi-0.1.18.dev1.data/data/lib/cmake/SPIRV-Tools-diff/SPIRV-Tools-diffTargets.cmake +123 -0
  31. gstaichi-0.1.18.dev1.data/data/lib/cmake/SPIRV-Tools-link/SPIRV-Tools-linkConfig.cmake +5 -0
  32. gstaichi-0.1.18.dev1.data/data/lib/cmake/SPIRV-Tools-link/SPIRV-Tools-linkTargets-release.cmake +19 -0
  33. gstaichi-0.1.18.dev1.data/data/lib/cmake/SPIRV-Tools-link/SPIRV-Tools-linkTargets.cmake +123 -0
  34. gstaichi-0.1.18.dev1.data/data/lib/cmake/SPIRV-Tools-lint/SPIRV-Tools-lintConfig.cmake +5 -0
  35. gstaichi-0.1.18.dev1.data/data/lib/cmake/SPIRV-Tools-lint/SPIRV-Tools-lintTargets-release.cmake +19 -0
  36. gstaichi-0.1.18.dev1.data/data/lib/cmake/SPIRV-Tools-lint/SPIRV-Tools-lintTargets.cmake +123 -0
  37. gstaichi-0.1.18.dev1.data/data/lib/cmake/SPIRV-Tools-opt/SPIRV-Tools-optConfig.cmake +5 -0
  38. gstaichi-0.1.18.dev1.data/data/lib/cmake/SPIRV-Tools-opt/SPIRV-Tools-optTargets-release.cmake +19 -0
  39. gstaichi-0.1.18.dev1.data/data/lib/cmake/SPIRV-Tools-opt/SPIRV-Tools-optTargets.cmake +123 -0
  40. gstaichi-0.1.18.dev1.data/data/lib/cmake/SPIRV-Tools-reduce/SPIRV-Tools-reduceConfig.cmake +5 -0
  41. gstaichi-0.1.18.dev1.data/data/lib/cmake/SPIRV-Tools-reduce/SPIRV-Tools-reduceTarget-release.cmake +19 -0
  42. gstaichi-0.1.18.dev1.data/data/lib/cmake/SPIRV-Tools-reduce/SPIRV-Tools-reduceTarget.cmake +123 -0
  43. gstaichi-0.1.18.dev1.data/data/lib/cmake/glfw3/glfw3Config.cmake +3 -0
  44. gstaichi-0.1.18.dev1.data/data/lib/cmake/glfw3/glfw3ConfigVersion.cmake +65 -0
  45. gstaichi-0.1.18.dev1.data/data/lib/cmake/glfw3/glfw3Targets-release.cmake +19 -0
  46. gstaichi-0.1.18.dev1.data/data/lib/cmake/glfw3/glfw3Targets.cmake +107 -0
  47. gstaichi-0.1.18.dev1.data/data/lib/libSPIRV-Tools-shared.dylib +0 -0
  48. gstaichi-0.1.18.dev1.data/data/share/spirv_cross_c/cmake/spirv_cross_cConfig-release.cmake +19 -0
  49. gstaichi-0.1.18.dev1.data/data/share/spirv_cross_c/cmake/spirv_cross_cConfig.cmake +123 -0
  50. gstaichi-0.1.18.dev1.data/data/share/spirv_cross_core/cmake/spirv_cross_coreConfig-release.cmake +19 -0
  51. gstaichi-0.1.18.dev1.data/data/share/spirv_cross_core/cmake/spirv_cross_coreConfig.cmake +106 -0
  52. gstaichi-0.1.18.dev1.data/data/share/spirv_cross_cpp/cmake/spirv_cross_cppConfig-release.cmake +19 -0
  53. gstaichi-0.1.18.dev1.data/data/share/spirv_cross_cpp/cmake/spirv_cross_cppConfig.cmake +123 -0
  54. gstaichi-0.1.18.dev1.data/data/share/spirv_cross_glsl/cmake/spirv_cross_glslConfig-release.cmake +19 -0
  55. gstaichi-0.1.18.dev1.data/data/share/spirv_cross_glsl/cmake/spirv_cross_glslConfig.cmake +123 -0
  56. gstaichi-0.1.18.dev1.data/data/share/spirv_cross_hlsl/cmake/spirv_cross_hlslConfig-release.cmake +19 -0
  57. gstaichi-0.1.18.dev1.data/data/share/spirv_cross_hlsl/cmake/spirv_cross_hlslConfig.cmake +123 -0
  58. gstaichi-0.1.18.dev1.data/data/share/spirv_cross_msl/cmake/spirv_cross_mslConfig-release.cmake +19 -0
  59. gstaichi-0.1.18.dev1.data/data/share/spirv_cross_msl/cmake/spirv_cross_mslConfig.cmake +123 -0
  60. gstaichi-0.1.18.dev1.data/data/share/spirv_cross_reflect/cmake/spirv_cross_reflectConfig-release.cmake +19 -0
  61. gstaichi-0.1.18.dev1.data/data/share/spirv_cross_reflect/cmake/spirv_cross_reflectConfig.cmake +106 -0
  62. gstaichi-0.1.18.dev1.data/data/share/spirv_cross_util/cmake/spirv_cross_utilConfig-release.cmake +19 -0
  63. gstaichi-0.1.18.dev1.data/data/share/spirv_cross_util/cmake/spirv_cross_utilConfig.cmake +123 -0
  64. gstaichi-0.1.18.dev1.dist-info/METADATA +108 -0
  65. gstaichi-0.1.18.dev1.dist-info/RECORD +219 -0
  66. gstaichi-0.1.18.dev1.dist-info/WHEEL +5 -0
  67. gstaichi-0.1.18.dev1.dist-info/entry_points.txt +2 -0
  68. gstaichi-0.1.18.dev1.dist-info/licenses/LICENSE +201 -0
  69. gstaichi-0.1.18.dev1.dist-info/top_level.txt +1 -0
  70. taichi/__init__.py +44 -0
  71. taichi/__main__.py +5 -0
  72. taichi/_funcs.py +706 -0
  73. taichi/_kernels.py +420 -0
  74. taichi/_lib/__init__.py +3 -0
  75. taichi/_lib/c_api/include/taichi/cpp/taichi.hpp +1401 -0
  76. taichi/_lib/c_api/include/taichi/taichi.h +29 -0
  77. taichi/_lib/c_api/include/taichi/taichi_core.h +1111 -0
  78. taichi/_lib/c_api/include/taichi/taichi_cpu.h +29 -0
  79. taichi/_lib/c_api/include/taichi/taichi_metal.h +72 -0
  80. taichi/_lib/c_api/include/taichi/taichi_platform.h +55 -0
  81. taichi/_lib/c_api/include/taichi/taichi_unity.h +64 -0
  82. taichi/_lib/c_api/include/taichi/taichi_vulkan.h +151 -0
  83. taichi/_lib/c_api/lib/libtaichi_c_api.dylib +0 -0
  84. taichi/_lib/c_api/runtime/libMoltenVK.dylib +0 -0
  85. taichi/_lib/c_api/runtime/runtime_arm64.bc +0 -0
  86. taichi/_lib/c_api/taichi/lib/cmake/taichi/TaichiConfig.cmake +29 -0
  87. taichi/_lib/c_api/taichi/lib/cmake/taichi/TaichiConfigVersion.cmake +65 -0
  88. taichi/_lib/c_api/taichi/lib/cmake/taichi/TaichiTargets.cmake +121 -0
  89. taichi/_lib/core/__init__.py +0 -0
  90. taichi/_lib/core/py.typed +0 -0
  91. taichi/_lib/core/taichi_python.cpython-310-darwin.so +0 -0
  92. taichi/_lib/core/taichi_python.pyi +3077 -0
  93. taichi/_lib/runtime/libMoltenVK.dylib +0 -0
  94. taichi/_lib/runtime/runtime_arm64.bc +0 -0
  95. taichi/_lib/utils.py +249 -0
  96. taichi/_logging.py +131 -0
  97. taichi/_main.py +552 -0
  98. taichi/_snode/__init__.py +5 -0
  99. taichi/_snode/fields_builder.py +189 -0
  100. taichi/_snode/snode_tree.py +34 -0
  101. taichi/_ti_module/__init__.py +3 -0
  102. taichi/_ti_module/cppgen.py +309 -0
  103. taichi/_ti_module/module.py +145 -0
  104. taichi/_version.py +1 -0
  105. taichi/_version_check.py +100 -0
  106. taichi/ad/__init__.py +3 -0
  107. taichi/ad/_ad.py +530 -0
  108. taichi/algorithms/__init__.py +3 -0
  109. taichi/algorithms/_algorithms.py +117 -0
  110. taichi/aot/__init__.py +12 -0
  111. taichi/aot/_export.py +28 -0
  112. taichi/aot/conventions/__init__.py +3 -0
  113. taichi/aot/conventions/gfxruntime140/__init__.py +38 -0
  114. taichi/aot/conventions/gfxruntime140/dr.py +244 -0
  115. taichi/aot/conventions/gfxruntime140/sr.py +613 -0
  116. taichi/aot/module.py +253 -0
  117. taichi/aot/utils.py +151 -0
  118. taichi/assets/.git +1 -0
  119. taichi/assets/Go-Regular.ttf +0 -0
  120. taichi/assets/static/imgs/ti_gallery.png +0 -0
  121. taichi/examples/minimal.py +28 -0
  122. taichi/experimental.py +16 -0
  123. taichi/graph/__init__.py +3 -0
  124. taichi/graph/_graph.py +292 -0
  125. taichi/lang/__init__.py +50 -0
  126. taichi/lang/_ndarray.py +348 -0
  127. taichi/lang/_ndrange.py +152 -0
  128. taichi/lang/_texture.py +172 -0
  129. taichi/lang/_wrap_inspect.py +189 -0
  130. taichi/lang/any_array.py +99 -0
  131. taichi/lang/argpack.py +411 -0
  132. taichi/lang/ast/__init__.py +5 -0
  133. taichi/lang/ast/ast_transformer.py +1806 -0
  134. taichi/lang/ast/ast_transformer_utils.py +328 -0
  135. taichi/lang/ast/checkers.py +106 -0
  136. taichi/lang/ast/symbol_resolver.py +57 -0
  137. taichi/lang/ast/transform.py +9 -0
  138. taichi/lang/common_ops.py +310 -0
  139. taichi/lang/exception.py +80 -0
  140. taichi/lang/expr.py +180 -0
  141. taichi/lang/field.py +464 -0
  142. taichi/lang/impl.py +1246 -0
  143. taichi/lang/kernel_arguments.py +157 -0
  144. taichi/lang/kernel_impl.py +1415 -0
  145. taichi/lang/matrix.py +1877 -0
  146. taichi/lang/matrix_ops.py +341 -0
  147. taichi/lang/matrix_ops_utils.py +190 -0
  148. taichi/lang/mesh.py +687 -0
  149. taichi/lang/misc.py +807 -0
  150. taichi/lang/ops.py +1489 -0
  151. taichi/lang/runtime_ops.py +13 -0
  152. taichi/lang/shell.py +35 -0
  153. taichi/lang/simt/__init__.py +5 -0
  154. taichi/lang/simt/block.py +94 -0
  155. taichi/lang/simt/grid.py +7 -0
  156. taichi/lang/simt/subgroup.py +191 -0
  157. taichi/lang/simt/warp.py +96 -0
  158. taichi/lang/snode.py +487 -0
  159. taichi/lang/source_builder.py +150 -0
  160. taichi/lang/struct.py +855 -0
  161. taichi/lang/util.py +381 -0
  162. taichi/linalg/__init__.py +8 -0
  163. taichi/linalg/matrixfree_cg.py +310 -0
  164. taichi/linalg/sparse_cg.py +59 -0
  165. taichi/linalg/sparse_matrix.py +303 -0
  166. taichi/linalg/sparse_solver.py +123 -0
  167. taichi/math/__init__.py +11 -0
  168. taichi/math/_complex.py +204 -0
  169. taichi/math/mathimpl.py +886 -0
  170. taichi/profiler/__init__.py +6 -0
  171. taichi/profiler/kernel_metrics.py +260 -0
  172. taichi/profiler/kernel_profiler.py +592 -0
  173. taichi/profiler/memory_profiler.py +15 -0
  174. taichi/profiler/scoped_profiler.py +36 -0
  175. taichi/shaders/Circles_vk.frag +29 -0
  176. taichi/shaders/Circles_vk.vert +45 -0
  177. taichi/shaders/Circles_vk_frag.spv +0 -0
  178. taichi/shaders/Circles_vk_vert.spv +0 -0
  179. taichi/shaders/Lines_vk.frag +9 -0
  180. taichi/shaders/Lines_vk.vert +11 -0
  181. taichi/shaders/Lines_vk_frag.spv +0 -0
  182. taichi/shaders/Lines_vk_vert.spv +0 -0
  183. taichi/shaders/Mesh_vk.frag +71 -0
  184. taichi/shaders/Mesh_vk.vert +68 -0
  185. taichi/shaders/Mesh_vk_frag.spv +0 -0
  186. taichi/shaders/Mesh_vk_vert.spv +0 -0
  187. taichi/shaders/Particles_vk.frag +95 -0
  188. taichi/shaders/Particles_vk.vert +73 -0
  189. taichi/shaders/Particles_vk_frag.spv +0 -0
  190. taichi/shaders/Particles_vk_vert.spv +0 -0
  191. taichi/shaders/SceneLines2quad_vk_comp.spv +0 -0
  192. taichi/shaders/SceneLines_vk.frag +9 -0
  193. taichi/shaders/SceneLines_vk.vert +12 -0
  194. taichi/shaders/SceneLines_vk_frag.spv +0 -0
  195. taichi/shaders/SceneLines_vk_vert.spv +0 -0
  196. taichi/shaders/SetImage_vk.frag +21 -0
  197. taichi/shaders/SetImage_vk.vert +15 -0
  198. taichi/shaders/SetImage_vk_frag.spv +0 -0
  199. taichi/shaders/SetImage_vk_vert.spv +0 -0
  200. taichi/shaders/Triangles_vk.frag +16 -0
  201. taichi/shaders/Triangles_vk.vert +29 -0
  202. taichi/shaders/Triangles_vk_frag.spv +0 -0
  203. taichi/shaders/Triangles_vk_vert.spv +0 -0
  204. taichi/shaders/lines2quad_vk_comp.spv +0 -0
  205. taichi/sparse/__init__.py +3 -0
  206. taichi/sparse/_sparse_grid.py +77 -0
  207. taichi/tools/__init__.py +12 -0
  208. taichi/tools/diagnose.py +124 -0
  209. taichi/tools/np2ply.py +364 -0
  210. taichi/tools/vtk.py +38 -0
  211. taichi/types/__init__.py +19 -0
  212. taichi/types/annotations.py +47 -0
  213. taichi/types/compound_types.py +90 -0
  214. taichi/types/enums.py +49 -0
  215. taichi/types/ndarray_type.py +147 -0
  216. taichi/types/primitive_types.py +203 -0
  217. taichi/types/quant.py +88 -0
  218. taichi/types/texture_type.py +85 -0
  219. taichi/types/utils.py +13 -0
taichi/lang/ops.py ADDED
@@ -0,0 +1,1489 @@
1
+ # type: ignore
2
+
3
+ import builtins
4
+ import functools
5
+ import operator as _bt_ops_mod # bt for builtin
6
+ from typing import Union
7
+
8
+ import numpy as np
9
+
10
+ from taichi._lib import core as _ti_core
11
+ from taichi.lang import expr, impl
12
+ from taichi.lang.exception import TaichiSyntaxError
13
+ from taichi.lang.field import Field
14
+ from taichi.lang.util import cook_dtype, is_matrix_class, is_taichi_class, taichi_scope
15
+
16
+
17
+ def stack_info():
18
+ return impl.get_runtime().get_current_src_info()
19
+
20
+
21
+ def is_taichi_expr(a):
22
+ return isinstance(a, expr.Expr)
23
+
24
+
25
+ def wrap_if_not_expr(a):
26
+ return (
27
+ expr.Expr(a, dbg_info=_ti_core.DebugInfo(impl.get_runtime().get_current_src_info()))
28
+ if not is_taichi_expr(a)
29
+ else a
30
+ )
31
+
32
+
33
+ def _read_matrix_or_scalar(x):
34
+ if is_matrix_class(x):
35
+ return x.to_numpy()
36
+ return x
37
+
38
+
39
+ def writeback_binary(foo):
40
+ @functools.wraps(foo)
41
+ def wrapped(a, b):
42
+ if isinstance(a, Field) or isinstance(b, Field):
43
+ return NotImplemented
44
+ if not (is_taichi_expr(a) and a.ptr.is_lvalue()):
45
+ raise TaichiSyntaxError(f"cannot use a non-writable target as the first operand of '{foo.__name__}'")
46
+ return foo(a, wrap_if_not_expr(b))
47
+
48
+ return wrapped
49
+
50
+
51
+ def cast(obj, dtype):
52
+ """Copy and cast a scalar or a matrix to a specified data type.
53
+ Must be called in Taichi scope.
54
+
55
+ Args:
56
+ obj (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
57
+ Input scalar or matrix.
58
+
59
+ dtype (:mod:`~taichi.types.primitive_types`): A primitive type defined in :mod:`~taichi.types.primitive_types`.
60
+
61
+ Returns:
62
+ A copy of `obj`, casted to the specified data type `dtype`.
63
+
64
+ Example::
65
+
66
+ >>> @ti.kernel
67
+ >>> def test():
68
+ >>> x = ti.Matrix([0, 1, 2], ti.i32)
69
+ >>> y = ti.cast(x, ti.f32)
70
+ >>> print(y)
71
+ >>>
72
+ >>> test()
73
+ [0.0, 1.0, 2.0]
74
+ """
75
+ dtype = cook_dtype(dtype)
76
+ if is_taichi_class(obj):
77
+ # TODO: unify with element_wise_unary
78
+ return obj.cast(dtype)
79
+ return expr.Expr(_ti_core.value_cast(expr.Expr(obj).ptr, dtype))
80
+
81
+
82
+ def bit_cast(obj, dtype):
83
+ """Copy and cast a scalar to a specified data type with its underlying
84
+ bits preserved. Must be called in taichi scope.
85
+
86
+ This function is equivalent to `reinterpret_cast` in C++.
87
+
88
+ Args:
89
+ obj (:mod:`~taichi.types.primitive_types`): Input scalar.
90
+
91
+ dtype (:mod:`~taichi.types.primitive_types`): Target data type, must have \
92
+ the same precision bits as the input (hence `f32` -> `f64` is not allowed).
93
+
94
+ Returns:
95
+ A copy of `obj`, casted to the specified data type `dtype`.
96
+
97
+ Example::
98
+
99
+ >>> @ti.kernel
100
+ >>> def test():
101
+ >>> x = 3.14
102
+ >>> y = ti.bit_cast(x, ti.i32)
103
+ >>> print(y) # 1078523331
104
+ >>>
105
+ >>> z = ti.bit_cast(y, ti.f32)
106
+ >>> print(z) # 3.14
107
+ """
108
+ dtype = cook_dtype(dtype)
109
+ if is_taichi_class(obj):
110
+ raise ValueError("Cannot apply bit_cast on Taichi classes")
111
+ else:
112
+ return expr.Expr(_ti_core.bits_cast(expr.Expr(obj).ptr, dtype))
113
+
114
+
115
+ def _unary_operation(taichi_op, python_op, a):
116
+ if isinstance(a, Field):
117
+ return NotImplemented
118
+ if is_taichi_expr(a):
119
+ return expr.Expr(taichi_op(a.ptr), dbg_info=_ti_core.DebugInfo(stack_info()))
120
+ from taichi.lang.matrix import Matrix # pylint: disable-msg=C0415
121
+
122
+ if isinstance(a, Matrix):
123
+ return Matrix(python_op(a.to_numpy()))
124
+ return python_op(a)
125
+
126
+
127
+ def _binary_operation(taichi_op, python_op, a, b):
128
+ if isinstance(a, Field) or isinstance(b, Field):
129
+ return NotImplemented
130
+ if is_taichi_expr(a) or is_taichi_expr(b):
131
+ a, b = wrap_if_not_expr(a), wrap_if_not_expr(b)
132
+ return expr.Expr(taichi_op(a.ptr, b.ptr), dbg_info=_ti_core.DebugInfo(stack_info()))
133
+ from taichi.lang.matrix import Matrix # pylint: disable-msg=C0415
134
+
135
+ if isinstance(a, Matrix) or isinstance(b, Matrix):
136
+ return Matrix(python_op(_read_matrix_or_scalar(a), _read_matrix_or_scalar(b)))
137
+ return python_op(a, b)
138
+
139
+
140
+ def _ternary_operation(taichi_op, python_op, a, b, c):
141
+ if isinstance(a, Field) or isinstance(b, Field) or isinstance(c, Field):
142
+ return NotImplemented
143
+ if is_taichi_expr(a) or is_taichi_expr(b) or is_taichi_expr(c):
144
+ a, b, c = wrap_if_not_expr(a), wrap_if_not_expr(b), wrap_if_not_expr(c)
145
+ return expr.Expr(taichi_op(a.ptr, b.ptr, c.ptr), dbg_info=_ti_core.DebugInfo(stack_info()))
146
+ from taichi.lang.matrix import Matrix # pylint: disable-msg=C0415
147
+
148
+ if isinstance(a, Matrix) or isinstance(b, Matrix) or isinstance(c, Matrix):
149
+ return Matrix(
150
+ python_op(
151
+ _read_matrix_or_scalar(a),
152
+ _read_matrix_or_scalar(b),
153
+ _read_matrix_or_scalar(c),
154
+ )
155
+ )
156
+ return python_op(a, b, c)
157
+
158
+
159
+ def neg(x):
160
+ """Numerical negative, element-wise.
161
+
162
+ Args:
163
+ x (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
164
+ Input scalar or matrix.
165
+
166
+ Returns:
167
+ Matrix or scalar `y`, so that `y = -x`. `y` has the same type as `x`.
168
+
169
+ Example::
170
+ >>> x = ti.Matrix([1, -1])
171
+ >>> y = ti.neg(a)
172
+ >>> y
173
+ [-1, 1]
174
+ """
175
+ return _unary_operation(_ti_core.expr_neg, _bt_ops_mod.neg, x)
176
+
177
+
178
+ def sin(x):
179
+ """Trigonometric sine, element-wise.
180
+
181
+ Args:
182
+ x (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
183
+ Angle, in radians.
184
+
185
+ Returns:
186
+ The sine of each element of `x`.
187
+
188
+ Example::
189
+
190
+ >>> from math import pi
191
+ >>> x = ti.Matrix([-pi/2., 0, pi/2.])
192
+ >>> ti.sin(x)
193
+ [-1., 0., 1.]
194
+ """
195
+ return _unary_operation(_ti_core.expr_sin, np.sin, x)
196
+
197
+
198
+ def cos(x):
199
+ """Trigonometric cosine, element-wise.
200
+
201
+ Args:
202
+ x (Union[:mod:`~taichi.type.primitive_types`, :class:`~taichi.Matrix`]): \
203
+ Angle, in radians.
204
+
205
+ Returns:
206
+ The cosine of each element of `x`.
207
+
208
+ Example::
209
+
210
+ >>> from math import pi
211
+ >>> x = ti.Matrix([-pi, 0, pi/2.])
212
+ >>> ti.cos(x)
213
+ [-1., 1., 0.]
214
+ """
215
+ return _unary_operation(_ti_core.expr_cos, np.cos, x)
216
+
217
+
218
+ def asin(x):
219
+ """Trigonometric inverse sine, element-wise.
220
+
221
+ The inverse of `sin` so that, if `y = sin(x)`, then `x = asin(y)`.
222
+
223
+ For input `x` not in the domain `[-1, 1]`, this function returns `nan` if \
224
+ it's called in taichi scope, or raises exception if it's called in python scope.
225
+
226
+ Args:
227
+ x (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
228
+ A scalar or a matrix with elements in [-1, 1].
229
+
230
+ Returns:
231
+ The inverse sine of each element in `x`, in radians and in the closed \
232
+ interval `[-pi/2, pi/2]`.
233
+
234
+ Example::
235
+
236
+ >>> from math import pi
237
+ >>> ti.asin(ti.Matrix([-1.0, 0.0, 1.0])) * 180 / pi
238
+ [-90., 0., 90.]
239
+ """
240
+ return _unary_operation(_ti_core.expr_asin, np.arcsin, x)
241
+
242
+
243
+ def acos(x):
244
+ """Trigonometric inverse cosine, element-wise.
245
+
246
+ The inverse of `cos` so that, if `y = cos(x)`, then `x = acos(y)`.
247
+
248
+ For input `x` not in the domain `[-1, 1]`, this function returns `nan` if \
249
+ it's called in taichi scope, or raises exception if it's called in python scope.
250
+
251
+ Args:
252
+ x (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
253
+ A scalar or a matrix with elements in [-1, 1].
254
+
255
+ Returns:
256
+ The inverse cosine of each element in `x`, in radians and in the closed \
257
+ interval `[0, pi]`. This is a scalar if `x` is a scalar.
258
+
259
+ Example::
260
+
261
+ >>> from math import pi
262
+ >>> ti.acos(ti.Matrix([-1.0, 0.0, 1.0])) * 180 / pi
263
+ [180., 90., 0.]
264
+ """
265
+ return _unary_operation(_ti_core.expr_acos, np.arccos, x)
266
+
267
+
268
+ def sqrt(x):
269
+ """Return the non-negative square-root of a scalar or a matrix,
270
+ element wise. If `x < 0` an exception is raised.
271
+
272
+ Args:
273
+ x (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
274
+ The scalar or matrix whose square-roots are required.
275
+
276
+ Returns:
277
+ The square-root `y` so that `y >= 0` and `y^2 = x`. `y` has the same type as `x`.
278
+
279
+ Example::
280
+
281
+ >>> x = ti.Matrix([1., 4., 9.])
282
+ >>> y = ti.sqrt(x)
283
+ >>> y
284
+ [1.0, 2.0, 3.0]
285
+ """
286
+ return _unary_operation(_ti_core.expr_sqrt, np.sqrt, x)
287
+
288
+
289
+ def rsqrt(x):
290
+ """The reciprocal of the square root function.
291
+
292
+ Args:
293
+ x (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
294
+ A scalar or a matrix.
295
+
296
+ Returns:
297
+ The reciprocal of `sqrt(x)`.
298
+ """
299
+
300
+ def _rsqrt(x):
301
+ return 1 / np.sqrt(x)
302
+
303
+ return _unary_operation(_ti_core.expr_rsqrt, _rsqrt, x)
304
+
305
+
306
+ def _round(x):
307
+ return _unary_operation(_ti_core.expr_round, np.round, x)
308
+
309
+
310
+ def round(x, dtype=None): # pylint: disable=redefined-builtin
311
+ """Round to the nearest integer, element-wise.
312
+
313
+ Args:
314
+ x (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
315
+ A scalar or a matrix.
316
+
317
+ dtype: (:mod:`~taichi.types.primitive_types`): the returned type, default to `None`. If \
318
+ set to `None` the retuned value will have the same type with `x`.
319
+
320
+ Returns:
321
+ The nearest integer of `x`, with return value type `dtype`.
322
+
323
+ Example::
324
+
325
+ >>> @ti.kernel
326
+ >>> def test():
327
+ >>> x = ti.Vector([-1.5, 1.2, 2.7])
328
+ >>> print(ti.round(x))
329
+ [-2., 1., 3.]
330
+ """
331
+ result = _round(x)
332
+ if dtype is not None:
333
+ result = cast(result, dtype)
334
+ return result
335
+
336
+
337
+ def _floor(x):
338
+ return _unary_operation(_ti_core.expr_floor, np.floor, x)
339
+
340
+
341
+ def floor(x, dtype=None):
342
+ """Return the floor of the input, element-wise.
343
+ The floor of the scalar `x` is the largest integer `k`, such that `k <= x`.
344
+
345
+ Args:
346
+ x (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
347
+ Input scalar or matrix.
348
+
349
+ dtype: (:mod:`~taichi.types.primitive_types`): the returned type, default to `None`. If \
350
+ set to `None` the retuned value will have the same type with `x`.
351
+
352
+ Returns:
353
+ The floor of each element in `x`, with return value type `dtype`.
354
+
355
+ Example::
356
+ >>> @ti.kernel
357
+ >>> def test():
358
+ >>> x = ti.Matrix([-1.1, 2.2, 3.])
359
+ >>> y = ti.floor(x, ti.f64)
360
+ >>> print(y) # [-2.000000000000, 2.000000000000, 3.000000000000]
361
+ """
362
+ result = _floor(x)
363
+ if dtype is not None:
364
+ result = cast(result, dtype)
365
+ return result
366
+
367
+
368
+ def _ceil(x):
369
+ return _unary_operation(_ti_core.expr_ceil, np.ceil, x)
370
+
371
+
372
+ def ceil(x, dtype=None):
373
+ """Return the ceiling of the input, element-wise.
374
+
375
+ The ceil of the scalar `x` is the smallest integer `k`, such that `k >= x`.
376
+
377
+ Args:
378
+ x (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
379
+ Input scalar or matrix.
380
+
381
+ dtype: (:mod:`~taichi.types.primitive_types`): the returned type, default to `None`. If \
382
+ set to `None` the retuned value will have the same type with `x`.
383
+
384
+ Returns:
385
+ The ceiling of each element in `x`, with return value type `dtype`.
386
+
387
+ Example::
388
+
389
+ >>> @ti.kernel
390
+ >>> def test():
391
+ >>> x = ti.Matrix([3.14, -1.5])
392
+ >>> y = ti.ceil(x)
393
+ >>> print(y) # [4.0, -1.0]
394
+ """
395
+ result = _ceil(x)
396
+ if dtype is not None:
397
+ result = cast(result, dtype)
398
+ return result
399
+
400
+
401
+ def frexp(x):
402
+ return _unary_operation(_ti_core.expr_frexp, np.frexp, x)
403
+
404
+
405
+ def tan(x):
406
+ """Trigonometric tangent function, element-wise.
407
+
408
+ Equivalent to `ti.sin(x)/ti.cos(x)` element-wise.
409
+
410
+ Args:
411
+ x (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
412
+ Input scalar or matrix.
413
+
414
+ Returns:
415
+ The tangent values of `x`.
416
+
417
+ Example::
418
+
419
+ >>> from math import pi
420
+ >>> @ti.kernel
421
+ >>> def test():
422
+ >>> x = ti.Matrix([-pi, pi/2, pi])
423
+ >>> y = ti.tan(x)
424
+ >>> print(y)
425
+ >>>
426
+ >>> test()
427
+ [-0.0, -22877334.0, 0.0]
428
+ """
429
+ return _unary_operation(_ti_core.expr_tan, np.tan, x)
430
+
431
+
432
+ def tanh(x):
433
+ """Compute the hyperbolic tangent of `x`, element-wise.
434
+
435
+ Args:
436
+ x (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
437
+ Input scalar or matrix.
438
+
439
+ Returns:
440
+ The corresponding hyperbolic tangent values.
441
+
442
+ Example::
443
+
444
+ >>> @ti.kernel
445
+ >>> def test():
446
+ >>> x = ti.Matrix([-1.0, 0.0, 1.0])
447
+ >>> y = ti.tanh(x)
448
+ >>> print(y)
449
+ >>>
450
+ >>> test()
451
+ [-0.761594, 0.000000, 0.761594]
452
+ """
453
+ return _unary_operation(_ti_core.expr_tanh, np.tanh, x)
454
+
455
+
456
+ def exp(x):
457
+ """Compute the exponential of all elements in `x`, element-wise.
458
+
459
+ Args:
460
+ x (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
461
+ Input scalar or matrix.
462
+
463
+ Returns:
464
+ Element-wise exponential of `x`.
465
+
466
+ Example::
467
+
468
+ >>> @ti.kernel
469
+ >>> def test():
470
+ >>> x = ti.Matrix([-1.0, 0.0, 1.0])
471
+ >>> y = ti.exp(x)
472
+ >>> print(y)
473
+ >>>
474
+ >>> test()
475
+ [0.367879, 1.000000, 2.718282]
476
+ """
477
+ return _unary_operation(_ti_core.expr_exp, np.exp, x)
478
+
479
+
480
+ def log(x):
481
+ """Compute the natural logarithm, element-wise.
482
+
483
+ The natural logarithm `log` is the inverse of the exponential function,
484
+ so that `log(exp(x)) = x`. The natural logarithm is logarithm in base `e`.
485
+
486
+ Args:
487
+ x (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
488
+ Input scalar or matrix.
489
+
490
+ Returns:
491
+ The natural logarithm of `x`, element-wise.
492
+
493
+ Example::
494
+
495
+ >>> @ti.kernel
496
+ >>> def test():
497
+ >>> x = ti.Vector([-1.0, 0.0, 1.0])
498
+ >>> y = ti.log(x)
499
+ >>> print(y)
500
+ >>>
501
+ >>> test()
502
+ [-nan, -inf, 0.000000]
503
+ """
504
+ return _unary_operation(_ti_core.expr_log, np.log, x)
505
+
506
+
507
+ def abs(x): # pylint: disable=W0622
508
+ """Compute the absolute value :math:`|x|` of `x`, element-wise.
509
+
510
+ Args:
511
+ x (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
512
+ Input scalar or matrix.
513
+
514
+ Returns:
515
+ The absolute value of each element in `x`.
516
+
517
+ Example::
518
+
519
+ >>> @ti.kernel
520
+ >>> def test():
521
+ >>> x = ti.Vector([-1.0, 0.0, 1.0])
522
+ >>> y = ti.abs(x)
523
+ >>> print(y)
524
+ >>>
525
+ >>> test()
526
+ [1.0, 0.0, 1.0]
527
+ """
528
+ return _unary_operation(_ti_core.expr_abs, builtins.abs, x)
529
+
530
+
531
+ def bit_not(a):
532
+ """The bit not function.
533
+
534
+ Args:
535
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): A number or a matrix.
536
+
537
+ Returns:
538
+ Bitwise not of `a`.
539
+ """
540
+ return _unary_operation(_ti_core.expr_bit_not, _bt_ops_mod.invert, a)
541
+
542
+
543
+ def popcnt(a):
544
+ def _popcnt(x):
545
+ return bin(x).count("1")
546
+
547
+ return _unary_operation(_ti_core.expr_popcnt, _popcnt, a)
548
+
549
+
550
+ def logical_not(a):
551
+ """The logical not function.
552
+
553
+ Args:
554
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): A number or a matrix.
555
+
556
+ Returns:
557
+ `1` iff `a=0`, otherwise `0`.
558
+ """
559
+ return _unary_operation(_ti_core.expr_logic_not, np.logical_not, a)
560
+
561
+
562
+ def random(dtype=float) -> Union[float, int]:
563
+ """Return a single random float/integer according to the specified data type.
564
+ Must be called in taichi scope.
565
+
566
+ If the required `dtype` is float type, this function returns a random number
567
+ sampled from the uniform distribution in the half-open interval [0, 1).
568
+
569
+ For integer types this function returns a random integer in the
570
+ half-open interval [0, 2^32) if a 32-bit integer is required,
571
+ or a random integer in the half-open interval [0, 2^64) if a
572
+ 64-bit integer is required.
573
+
574
+ Args:
575
+ dtype (:mod:`~taichi.types.primitive_types`): Type of the required random value.
576
+
577
+ Returns:
578
+ A random value with type `dtype`.
579
+
580
+ Example::
581
+
582
+ >>> @ti.kernel
583
+ >>> def test():
584
+ >>> x = ti.random(float)
585
+ >>> print(x) # 0.090257
586
+ >>>
587
+ >>> y = ti.random(ti.f64)
588
+ >>> print(y) # 0.716101627301
589
+ >>>
590
+ >>> i = ti.random(ti.i32)
591
+ >>> print(i) # -963722261
592
+ >>>
593
+ >>> j = ti.random(ti.i64)
594
+ >>> print(j) # 73412986184350777
595
+ """
596
+ dtype = cook_dtype(dtype)
597
+ x = expr.Expr(_ti_core.make_rand_expr(dtype, _ti_core.DebugInfo(impl.get_runtime().get_current_src_info())))
598
+ return impl.expr_init(x)
599
+
600
+
601
+ # NEXT: add matpow(self, power)
602
+
603
+
604
+ def add(a, b):
605
+ """The add function.
606
+
607
+ Args:
608
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): A number or a matrix.
609
+ b (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): A number or a matrix.
610
+
611
+ Returns:
612
+ sum of `a` and `b`.
613
+ """
614
+ return _binary_operation(_ti_core.expr_add, _bt_ops_mod.add, a, b)
615
+
616
+
617
+ def sub(a, b):
618
+ """The sub function.
619
+
620
+ Args:
621
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): A number or a matrix.
622
+ b (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): A number or a matrix.
623
+
624
+ Returns:
625
+ `a` subtract `b`.
626
+ """
627
+ return _binary_operation(_ti_core.expr_sub, _bt_ops_mod.sub, a, b)
628
+
629
+
630
+ def mul(a, b):
631
+ """The multiply function.
632
+
633
+ Args:
634
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): A number or a matrix.
635
+ b (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): A number or a matrix.
636
+
637
+ Returns:
638
+ `a` multiplied by `b`.
639
+ """
640
+ return _binary_operation(_ti_core.expr_mul, _bt_ops_mod.mul, a, b)
641
+
642
+
643
+ def mod(x1, x2):
644
+ """Returns the element-wise remainder of division.
645
+
646
+ This is equivalent to the Python modulus operator `x1 % x2` and
647
+ has the same sign as the divisor x2.
648
+
649
+ Args:
650
+ x1 (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
651
+ Dividend scalar or matrix.
652
+
653
+ x2 (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
654
+ Divisor scalar or matrix. When both `x1` and `x2` are matrices they must have the same shape.
655
+
656
+ Returns:
657
+ The element-wise remainder of the quotient `floordiv(x1, x2)`. This is a scalar \
658
+ if both `x1` and `x2` are scalars.
659
+
660
+ Example::
661
+
662
+ >>> @ti.kernel
663
+ >>> def test():
664
+ >>> x = ti.Matrix([3.0, 4.0, 5.0])
665
+ >>> y = 3
666
+ >>> z = ti.mod(y, x)
667
+ >>> print(z)
668
+ >>>
669
+ >>> test()
670
+ [1.0, 0.0, 4.0]
671
+ """
672
+
673
+ def expr_python_mod(a, b):
674
+ # a % b = a - (a // b) * b
675
+ quotient = expr.Expr(_ti_core.expr_floordiv(a, b))
676
+ multiply = expr.Expr(_ti_core.expr_mul(b, quotient.ptr))
677
+ return _ti_core.expr_sub(a, multiply.ptr)
678
+
679
+ return _binary_operation(expr_python_mod, _bt_ops_mod.mod, x1, x2)
680
+
681
+
682
+ def pow(base, exponent): # pylint: disable=W0622
683
+ """First array elements raised to second array elements :math:`{base}^{exponent}`, element-wise.
684
+
685
+ The result type of two scalar operands is determined as follows:
686
+ - If the exponent is an integral value, then the result type takes the type of the base.
687
+ - Otherwise, the result type follows
688
+ [Implicit type casting in binary operations](https://docs.taichi-lang.org/docs/type#implicit-type-casting-in-binary-operations).
689
+
690
+ With the above rules, an integral value raised to a negative integral value cannot have a
691
+ feasible type. Therefore, an exception will be raised if debug mode or optimization passes
692
+ are on; otherwise 1 will be returned.
693
+
694
+ In the following situations, the result is undefined:
695
+ - A negative value raised to a non-integral value.
696
+ - A zero value raised to a non-positive value.
697
+
698
+ Args:
699
+ base (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
700
+ The bases.
701
+ exponent (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
702
+ The exponents.
703
+
704
+ Returns:
705
+ `base` raised to `exponent`. This is a scalar if both `base` and `exponent` are scalars.
706
+
707
+ Example::
708
+
709
+ >>> @ti.kernel
710
+ >>> def test():
711
+ >>> x = ti.Matrix([-2.0, 2.0])
712
+ >>> y = -3
713
+ >>> z = ti.pow(x, y)
714
+ >>> print(z)
715
+ >>>
716
+ >>> test()
717
+ [-0.125000, 0.125000]
718
+ """
719
+ return _binary_operation(_ti_core.expr_pow, _bt_ops_mod.pow, base, exponent)
720
+
721
+
722
+ def floordiv(a, b):
723
+ """The floor division function.
724
+
725
+ Args:
726
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): A number or a matrix.
727
+ b (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): A number or a matrix with elements not equal to zero.
728
+
729
+ Returns:
730
+ The floor function of `a` divided by `b`.
731
+ """
732
+ return _binary_operation(_ti_core.expr_floordiv, _bt_ops_mod.floordiv, a, b)
733
+
734
+
735
+ def truediv(a, b):
736
+ """True division function.
737
+
738
+ Args:
739
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): A number or a matrix.
740
+ b (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): A number or a matrix with elements not equal to zero.
741
+
742
+ Returns:
743
+ The true value of `a` divided by `b`.
744
+ """
745
+ return _binary_operation(_ti_core.expr_truediv, _bt_ops_mod.truediv, a, b)
746
+
747
+
748
+ def max_impl(a, b):
749
+ """The maxnimum function.
750
+
751
+ Args:
752
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): A number or a matrix.
753
+ b (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): A number or a matrix.
754
+
755
+ Returns:
756
+ The maxnimum of `a` and `b`.
757
+ """
758
+ return _binary_operation(_ti_core.expr_max, np.maximum, a, b)
759
+
760
+
761
+ def min_impl(a, b):
762
+ """The minimum function.
763
+
764
+ Args:
765
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): A number or a matrix.
766
+ b (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): A number or a matrix.
767
+
768
+ Returns:
769
+ The minimum of `a` and `b`.
770
+ """
771
+ return _binary_operation(_ti_core.expr_min, np.minimum, a, b)
772
+
773
+
774
+ def atan2(x1, x2):
775
+ """Element-wise arc tangent of `x1/x2`.
776
+
777
+ Args:
778
+ x1 (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
779
+ y-coordinates.
780
+ x2 (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
781
+ x-coordinates.
782
+
783
+ Returns:
784
+ Angles in radians, in the range `[-pi, pi]`.
785
+ This is a scalar if both `x1` and `x2` are scalars.
786
+
787
+ Example::
788
+
789
+ >>> from math import pi
790
+ >>> @ti.kernel
791
+ >>> def test():
792
+ >>> x = ti.Matrix([-1.0, 1.0, -1.0, 1.0])
793
+ >>> y = ti.Matrix([-1.0, -1.0, 1.0, 1.0])
794
+ >>> z = ti.atan2(y, x) * 180 / pi
795
+ >>> print(z)
796
+ >>>
797
+ >>> test()
798
+ [-135.0, -45.0, 135.0, 45.0]
799
+ """
800
+ return _binary_operation(_ti_core.expr_atan2, np.arctan2, x1, x2)
801
+
802
+
803
+ def raw_div(x1, x2):
804
+ """Return `x1 // x2` if both `x1`, `x2` are integers, otherwise return `x1/x2`.
805
+
806
+ Args:
807
+ x1 (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): Dividend.
808
+ x2 (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): Divisor.
809
+
810
+ Returns:
811
+ Return `x1 // x2` if both `x1`, `x2` are integers, otherwise return `x1/x2`.
812
+
813
+ Example::
814
+
815
+ >>> @ti.kernel
816
+ >>> def main():
817
+ >>> x = 5
818
+ >>> y = 3
819
+ >>> print(raw_div(x, y)) # 1
820
+ >>> z = 4.0
821
+ >>> print(raw_div(x, z)) # 1.25
822
+ """
823
+
824
+ def c_div(a, b):
825
+ if isinstance(a, int) and isinstance(b, int):
826
+ return a // b
827
+ return a / b
828
+
829
+ return _binary_operation(_ti_core.expr_div, c_div, x1, x2)
830
+
831
+
832
+ def raw_mod(x1, x2):
833
+ """Return the remainder of `x1/x2`, element-wise.
834
+ This is the C-style `mod` function.
835
+
836
+ Args:
837
+ x1 (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
838
+ The dividend.
839
+ x2 (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
840
+ The divisor.
841
+
842
+ Returns:
843
+ The remainder of `x1` divided by `x2`.
844
+
845
+ Example::
846
+
847
+ >>> @ti.kernel
848
+ >>> def main():
849
+ >>> print(ti.mod(-4, 3)) # 2
850
+ >>> print(ti.raw_mod(-4, 3)) # -1
851
+ """
852
+
853
+ def c_mod(x, y):
854
+ return x - y * int(float(x) / y)
855
+
856
+ return _binary_operation(_ti_core.expr_mod, c_mod, x1, x2)
857
+
858
+
859
+ def cmp_lt(a, b):
860
+ """Compare two values (less than)
861
+
862
+ Args:
863
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value LHS
864
+ b (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value RHS
865
+
866
+ Returns:
867
+ Union[:class:`~taichi.lang.expr.Expr`, bool]: True if LHS is strictly smaller than RHS, False otherwise
868
+
869
+ """
870
+ return _binary_operation(_ti_core.expr_cmp_lt, _bt_ops_mod.lt, a, b)
871
+
872
+
873
+ def cmp_le(a, b):
874
+ """Compare two values (less than or equal to)
875
+
876
+ Args:
877
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value LHS
878
+ b (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value RHS
879
+
880
+ Returns:
881
+ Union[:class:`~taichi.lang.expr.Expr`, bool]: True if LHS is smaller than or equal to RHS, False otherwise
882
+
883
+ """
884
+ return _binary_operation(_ti_core.expr_cmp_le, _bt_ops_mod.le, a, b)
885
+
886
+
887
+ def cmp_gt(a, b):
888
+ """Compare two values (greater than)
889
+
890
+ Args:
891
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value LHS
892
+ b (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value RHS
893
+
894
+ Returns:
895
+ Union[:class:`~taichi.lang.expr.Expr`, bool]: True if LHS is strictly larger than RHS, False otherwise
896
+
897
+ """
898
+ return _binary_operation(_ti_core.expr_cmp_gt, _bt_ops_mod.gt, a, b)
899
+
900
+
901
+ def cmp_ge(a, b):
902
+ """Compare two values (greater than or equal to)
903
+
904
+ Args:
905
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value LHS
906
+ b (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value RHS
907
+
908
+ Returns:
909
+ bool: True if LHS is greater than or equal to RHS, False otherwise
910
+
911
+ """
912
+ return _binary_operation(_ti_core.expr_cmp_ge, _bt_ops_mod.ge, a, b)
913
+
914
+
915
+ def cmp_eq(a, b):
916
+ """Compare two values (equal to)
917
+
918
+ Args:
919
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value LHS
920
+ b (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value RHS
921
+
922
+ Returns:
923
+ Union[:class:`~taichi.lang.expr.Expr`, bool]: True if LHS is equal to RHS, False otherwise.
924
+
925
+ """
926
+ return _binary_operation(_ti_core.expr_cmp_eq, _bt_ops_mod.eq, a, b)
927
+
928
+
929
+ def cmp_ne(a, b):
930
+ """Compare two values (not equal to)
931
+
932
+ Args:
933
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value LHS
934
+ b (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value RHS
935
+
936
+ Returns:
937
+ Union[:class:`~taichi.lang.expr.Expr`, bool]: True if LHS is not equal to RHS, False otherwise
938
+
939
+ """
940
+ return _binary_operation(_ti_core.expr_cmp_ne, _bt_ops_mod.ne, a, b)
941
+
942
+
943
+ def bit_or(a, b):
944
+ """Computes bitwise-or
945
+
946
+ Args:
947
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value LHS
948
+ b (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value RHS
949
+
950
+ Returns:
951
+ Union[:class:`~taichi.lang.expr.Expr`, bool]: LHS bitwise-or with RHS
952
+
953
+ """
954
+ return _binary_operation(_ti_core.expr_bit_or, _bt_ops_mod.or_, a, b)
955
+
956
+
957
+ def bit_and(a, b):
958
+ """Compute bitwise-and
959
+
960
+ Args:
961
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value LHS
962
+ b (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value RHS
963
+
964
+ Returns:
965
+ Union[:class:`~taichi.lang.expr.Expr`, bool]: LHS bitwise-and with RHS
966
+
967
+ """
968
+ return _binary_operation(_ti_core.expr_bit_and, _bt_ops_mod.and_, a, b)
969
+
970
+
971
+ def bit_xor(a, b):
972
+ """Compute bitwise-xor
973
+
974
+ Args:
975
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value LHS
976
+ b (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value RHS
977
+
978
+ Returns:
979
+ Union[:class:`~taichi.lang.expr.Expr`, bool]: LHS bitwise-xor with RHS
980
+
981
+ """
982
+ return _binary_operation(_ti_core.expr_bit_xor, _bt_ops_mod.xor, a, b)
983
+
984
+
985
+ def bit_shl(a, b):
986
+ """Compute bitwise shift left
987
+
988
+ Args:
989
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value LHS
990
+ b (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value RHS
991
+
992
+ Returns:
993
+ Union[:class:`~taichi.lang.expr.Expr`, int]: LHS << RHS
994
+
995
+ """
996
+ return _binary_operation(_ti_core.expr_bit_shl, _bt_ops_mod.lshift, a, b)
997
+
998
+
999
+ def bit_sar(a, b):
1000
+ """Compute bitwise shift right
1001
+
1002
+ Args:
1003
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value LHS
1004
+ b (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value RHS
1005
+
1006
+ Returns:
1007
+ Union[:class:`~taichi.lang.expr.Expr`, int]: LHS >> RHS
1008
+
1009
+ """
1010
+ return _binary_operation(_ti_core.expr_bit_sar, _bt_ops_mod.rshift, a, b)
1011
+
1012
+
1013
+ @taichi_scope
1014
+ def bit_shr(x1, x2):
1015
+ """Elements in `x1` shifted to the right by number of bits in `x2`.
1016
+ Both `x1`, `x2` must have integer type.
1017
+
1018
+ Args:
1019
+ x1 (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
1020
+ Input data.
1021
+ x2 (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
1022
+ Number of bits to remove at the right of `x1`.
1023
+
1024
+ Returns:
1025
+ Return `x1` with bits shifted `x2` times to the right.
1026
+ This is a scalar if both `x1` and `x2` are scalars.
1027
+
1028
+ Example::
1029
+ >>> @ti.kernel
1030
+ >>> def main():
1031
+ >>> x = ti.Matrix([7, 8])
1032
+ >>> y = ti.Matrix([1, 2])
1033
+ >>> print(ti.bit_shr(x, y))
1034
+ >>>
1035
+ >>> main()
1036
+ [3, 2]
1037
+ """
1038
+ return _binary_operation(_ti_core.expr_bit_shr, _bt_ops_mod.rshift, x1, x2)
1039
+
1040
+
1041
+ def logical_and(a, b):
1042
+ """Compute logical_and
1043
+
1044
+ Args:
1045
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value LHS
1046
+ b (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value RHS
1047
+
1048
+ Returns:
1049
+ Union[:class:`~taichi.lang.expr.Expr`, bool]: LHS logical-and RHS (with short-circuit semantics)
1050
+
1051
+ """
1052
+ return _binary_operation(_ti_core.expr_logical_and, lambda a, b: a and b, a, b)
1053
+
1054
+
1055
+ def logical_or(a, b):
1056
+ """Compute logical_or
1057
+
1058
+ Args:
1059
+ a (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value LHS
1060
+ b (Union[:class:`~taichi.lang.expr.Expr`, :class:`~taichi.lang.matrix.Matrix`]): value RHS
1061
+
1062
+ Returns:
1063
+ Union[:class:`~taichi.lang.expr.Expr`, bool]: LHS logical-or RHS (with short-circuit semantics)
1064
+
1065
+ """
1066
+ return _binary_operation(_ti_core.expr_logical_or, lambda a, b: a or b, a, b)
1067
+
1068
+
1069
+ def select(cond, x1, x2):
1070
+ """Return an array drawn from elements in `x1` or `x2`,
1071
+ depending on the conditions in `cond`.
1072
+
1073
+ Args:
1074
+ cond (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
1075
+ The array of conditions.
1076
+ x1, x2 (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
1077
+ The arrays where the output elements are taken from.
1078
+
1079
+ Returns:
1080
+ The output at position `k` is the k-th element of `x1` if the k-th element
1081
+ in `cond` is `True`, otherwise it's the k-th element of `x2`.
1082
+
1083
+ Example::
1084
+
1085
+ >>> @ti.kernel
1086
+ >>> def main():
1087
+ >>> cond = ti.Matrix([0, 1, 0, 1])
1088
+ >>> x = ti.Matrix([1, 2, 3, 4])
1089
+ >>> y = ti.Matrix([-1, -2, -3, -4])
1090
+ >>> print(ti.select(cond, x, y))
1091
+ >>>
1092
+ >>> main()
1093
+ [-1, 2, -3, 4]
1094
+ """
1095
+ # TODO: systematically resolve `-1 = True` problem by introducing u1:
1096
+ cond = logical_not(logical_not(cond))
1097
+
1098
+ def py_select(cond, x1, x2):
1099
+ return x1 * cond + x2 * (1 - cond)
1100
+
1101
+ return _ternary_operation(_ti_core.expr_select, py_select, cond, x1, x2)
1102
+
1103
+
1104
+ def ifte(cond, x1, x2):
1105
+ """Evaluate and return `x1` if `cond` is true; otherwise evaluate and return `x2`. This operator guarantees
1106
+ short-circuit semantics: exactly one of `x1` or `x2` will be evaluated.
1107
+
1108
+ Args:
1109
+ cond (:mod:`~taichi.types.primitive_types`): \
1110
+ The condition.
1111
+ x1, x2 (:mod:`~taichi.types.primitive_types`): \
1112
+ The outputs.
1113
+
1114
+ Returns:
1115
+ `x1` if `cond` is true and `x2` otherwise.
1116
+ """
1117
+ # TODO: systematically resolve `-1 = True` problem by introducing u1:
1118
+ cond = logical_not(logical_not(cond))
1119
+
1120
+ def py_ifte(cond, x1, x2):
1121
+ return x1 if cond else x2
1122
+
1123
+ return _ternary_operation(_ti_core.expr_ifte, py_ifte, cond, x1, x2)
1124
+
1125
+
1126
+ def clz(a):
1127
+ """Count the number of leading zeros for a 32bit integer"""
1128
+
1129
+ def _clz(x):
1130
+ for i in range(32):
1131
+ if 2**i > x:
1132
+ return 32 - i
1133
+ return 0
1134
+
1135
+ return _unary_operation(_ti_core.expr_clz, _clz, a)
1136
+
1137
+
1138
+ @writeback_binary
1139
+ def atomic_add(x, y):
1140
+ """Atomically compute `x + y`, store the result in `x`,
1141
+ and return the old value of `x`.
1142
+
1143
+ `x` must be a writable target, constant expressions or scalars
1144
+ are not allowed.
1145
+
1146
+ Args:
1147
+ x, y (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
1148
+ The input.
1149
+
1150
+ Returns:
1151
+ The old value of `x`.
1152
+
1153
+ Example::
1154
+
1155
+ >>> @ti.kernel
1156
+ >>> def test():
1157
+ >>> x = ti.Vector([0, 0, 0])
1158
+ >>> y = ti.Vector([1, 2, 3])
1159
+ >>> z = ti.atomic_add(x, y)
1160
+ >>> print(x) # [1, 2, 3] the new value of x
1161
+ >>> print(z) # [0, 0, 0], the old value of x
1162
+ >>>
1163
+ >>> ti.atomic_add(1, x) # will raise TaichiSyntaxError
1164
+ """
1165
+ return impl.expr_init(expr.Expr(_ti_core.expr_atomic_add(x.ptr, y.ptr), dbg_info=_ti_core.DebugInfo(stack_info())))
1166
+
1167
+
1168
+ @writeback_binary
1169
+ def atomic_mul(x, y):
1170
+ """Atomically compute `x * y`, store the result in `x`,
1171
+ and return the old value of `x`.
1172
+
1173
+ `x` must be a writable target, constant expressions or scalars
1174
+ are not allowed.
1175
+
1176
+ Args:
1177
+ x, y (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
1178
+ The input.
1179
+
1180
+ Returns:
1181
+ The old value of `x`.
1182
+
1183
+ Example::
1184
+
1185
+ >>> @ti.kernel
1186
+ >>> def test():
1187
+ >>> x = ti.Vector([1, 2, 3])
1188
+ >>> y = ti.Vector([4, 5, 6])
1189
+ >>> z = ti.atomic_mul(x, y)
1190
+ >>> print(x) # [1, 2, 3] the new value of x
1191
+ >>> print(z) # [4, 10, 18], the old value of x
1192
+ >>>
1193
+ >>> ti.atomic_mul(1, x) # will raise TaichiSyntaxError
1194
+ """
1195
+ return impl.expr_init(expr.Expr(_ti_core.expr_atomic_mul(x.ptr, y.ptr), dbg_info=_ti_core.DebugInfo(stack_info())))
1196
+
1197
+
1198
+ @writeback_binary
1199
+ def atomic_sub(x, y):
1200
+ """Atomically subtract `x` by `y`, store the result in `x`,
1201
+ and return the old value of `x`.
1202
+
1203
+ `x` must be a writable target, constant expressions or scalars
1204
+ are not allowed.
1205
+
1206
+ Args:
1207
+ x, y (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
1208
+ The input.
1209
+
1210
+ Returns:
1211
+ The old value of `x`.
1212
+
1213
+ Example::
1214
+
1215
+ >>> @ti.kernel
1216
+ >>> def test():
1217
+ >>> x = ti.Vector([0, 0, 0])
1218
+ >>> y = ti.Vector([1, 2, 3])
1219
+ >>> z = ti.atomic_sub(x, y)
1220
+ >>> print(x) # [-1, -2, -3] the new value of x
1221
+ >>> print(z) # [0, 0, 0], the old value of x
1222
+ >>>
1223
+ >>> ti.atomic_sub(1, x) # will raise TaichiSyntaxError
1224
+ """
1225
+ return impl.expr_init(expr.Expr(_ti_core.expr_atomic_sub(x.ptr, y.ptr), dbg_info=_ti_core.DebugInfo(stack_info())))
1226
+
1227
+
1228
+ @writeback_binary
1229
+ def atomic_min(x, y):
1230
+ """Atomically compute the minimum of `x` and `y`, element-wise.
1231
+ Store the result in `x`, and return the old value of `x`.
1232
+
1233
+ `x` must be a writable target, constant expressions or scalars
1234
+ are not allowed.
1235
+
1236
+ Args:
1237
+ x, y (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
1238
+ The input.
1239
+
1240
+ Returns:
1241
+ The old value of `x`.
1242
+
1243
+ Example::
1244
+
1245
+ >>> @ti.kernel
1246
+ >>> def test():
1247
+ >>> x = 2
1248
+ >>> y = 1
1249
+ >>> z = ti.atomic_min(x, y)
1250
+ >>> print(x) # 1 the new value of x
1251
+ >>> print(z) # 2, the old value of x
1252
+ >>>
1253
+ >>> ti.atomic_min(1, x) # will raise TaichiSyntaxError
1254
+ """
1255
+ return impl.expr_init(expr.Expr(_ti_core.expr_atomic_min(x.ptr, y.ptr), dbg_info=_ti_core.DebugInfo(stack_info())))
1256
+
1257
+
1258
+ @writeback_binary
1259
+ def atomic_max(x, y):
1260
+ """Atomically compute the maximum of `x` and `y`, element-wise.
1261
+ Store the result in `x`, and return the old value of `x`.
1262
+
1263
+ `x` must be a writable target, constant expressions or scalars
1264
+ are not allowed.
1265
+
1266
+ Args:
1267
+ x, y (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
1268
+ The input.
1269
+
1270
+ Returns:
1271
+ The old value of `x`.
1272
+
1273
+ Example::
1274
+
1275
+ >>> @ti.kernel
1276
+ >>> def test():
1277
+ >>> x = 1
1278
+ >>> y = 2
1279
+ >>> z = ti.atomic_max(x, y)
1280
+ >>> print(x) # 2 the new value of x
1281
+ >>> print(z) # 1, the old value of x
1282
+ >>>
1283
+ >>> ti.atomic_max(1, x) # will raise TaichiSyntaxError
1284
+ """
1285
+ return impl.expr_init(expr.Expr(_ti_core.expr_atomic_max(x.ptr, y.ptr), dbg_info=_ti_core.DebugInfo(stack_info())))
1286
+
1287
+
1288
+ @writeback_binary
1289
+ def atomic_and(x, y):
1290
+ """Atomically compute the bit-wise AND of `x` and `y`, element-wise.
1291
+ Store the result in `x`, and return the old value of `x`.
1292
+
1293
+ `x` must be a writable target, constant expressions or scalars
1294
+ are not allowed.
1295
+
1296
+ Args:
1297
+ x, y (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
1298
+ The input. When both are matrices they must have the same shape.
1299
+
1300
+ Returns:
1301
+ The old value of `x`.
1302
+
1303
+ Example::
1304
+
1305
+ >>> @ti.kernel
1306
+ >>> def test():
1307
+ >>> x = ti.Vector([-1, 0, 1])
1308
+ >>> y = ti.Vector([1, 2, 3])
1309
+ >>> z = ti.atomic_and(x, y)
1310
+ >>> print(x) # [1, 0, 1] the new value of x
1311
+ >>> print(z) # [-1, 0, 1], the old value of x
1312
+ >>>
1313
+ >>> ti.atomic_and(1, x) # will raise TaichiSyntaxError
1314
+ """
1315
+ return impl.expr_init(
1316
+ expr.Expr(_ti_core.expr_atomic_bit_and(x.ptr, y.ptr), dbg_info=_ti_core.DebugInfo(stack_info()))
1317
+ )
1318
+
1319
+
1320
+ @writeback_binary
1321
+ def atomic_or(x, y):
1322
+ """Atomically compute the bit-wise OR of `x` and `y`, element-wise.
1323
+ Store the result in `x`, and return the old value of `x`.
1324
+
1325
+ `x` must be a writable target, constant expressions or scalars
1326
+ are not allowed.
1327
+
1328
+ Args:
1329
+ x, y (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
1330
+ The input. When both are matrices they must have the same shape.
1331
+
1332
+ Returns:
1333
+ The old value of `x`.
1334
+
1335
+ Example::
1336
+
1337
+ >>> @ti.kernel
1338
+ >>> def test():
1339
+ >>> x = ti.Vector([-1, 0, 1])
1340
+ >>> y = ti.Vector([1, 2, 3])
1341
+ >>> z = ti.atomic_or(x, y)
1342
+ >>> print(x) # [-1, 2, 3] the new value of x
1343
+ >>> print(z) # [-1, 0, 1], the old value of x
1344
+ >>>
1345
+ >>> ti.atomic_or(1, x) # will raise TaichiSyntaxError
1346
+ """
1347
+ return impl.expr_init(
1348
+ expr.Expr(_ti_core.expr_atomic_bit_or(x.ptr, y.ptr), dbg_info=_ti_core.DebugInfo(stack_info()))
1349
+ )
1350
+
1351
+
1352
+ @writeback_binary
1353
+ def atomic_xor(x, y):
1354
+ """Atomically compute the bit-wise XOR of `x` and `y`, element-wise.
1355
+ Store the result in `x`, and return the old value of `x`.
1356
+
1357
+ `x` must be a writable target, constant expressions or scalars
1358
+ are not allowed.
1359
+
1360
+ Args:
1361
+ x, y (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
1362
+ The input. When both are matrices they must have the same shape.
1363
+
1364
+ Returns:
1365
+ The old value of `x`.
1366
+
1367
+ Example::
1368
+
1369
+ >>> @ti.kernel
1370
+ >>> def test():
1371
+ >>> x = ti.Vector([-1, 0, 1])
1372
+ >>> y = ti.Vector([1, 2, 3])
1373
+ >>> z = ti.atomic_xor(x, y)
1374
+ >>> print(x) # [-2, 2, 2] the new value of x
1375
+ >>> print(z) # [-1, 0, 1], the old value of x
1376
+ >>>
1377
+ >>> ti.atomic_xor(1, x) # will raise TaichiSyntaxError
1378
+ """
1379
+ return impl.expr_init(
1380
+ expr.Expr(_ti_core.expr_atomic_bit_xor(x.ptr, y.ptr), dbg_info=_ti_core.DebugInfo(stack_info()))
1381
+ )
1382
+
1383
+
1384
+ @writeback_binary
1385
+ def assign(a, b):
1386
+ impl.get_runtime().compiling_callable.ast_builder().expr_assign(a.ptr, b.ptr, _ti_core.DebugInfo(stack_info()))
1387
+ return a
1388
+
1389
+
1390
+ def max(*args): # pylint: disable=W0622
1391
+ """Compute the maximum of the arguments, element-wise.
1392
+
1393
+ This function takes no effect on a single argument, even it's array-like.
1394
+ When there are both scalar and matrix arguments in `args`, the matrices
1395
+ must have the same shape, and scalars will be broadcasted to the same shape as the matrix.
1396
+
1397
+ Args:
1398
+ args: (List[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
1399
+ The input.
1400
+
1401
+ Returns:
1402
+ Maximum of the inputs.
1403
+
1404
+ Example::
1405
+
1406
+ >>> @ti.kernel
1407
+ >>> def foo():
1408
+ >>> x = ti.Vector([0, 1, 2])
1409
+ >>> y = ti.Vector([3, 4, 5])
1410
+ >>> z = ti.max(x, y, 4)
1411
+ >>> print(z) # [4, 4, 5]
1412
+ """
1413
+ num_args = len(args)
1414
+ assert num_args >= 1
1415
+ if num_args == 1:
1416
+ return args[0]
1417
+ if num_args == 2:
1418
+ return max_impl(args[0], args[1])
1419
+ return max_impl(args[0], max(*args[1:]))
1420
+
1421
+
1422
+ def min(*args): # pylint: disable=W0622
1423
+ """Compute the minimum of the arguments, element-wise.
1424
+
1425
+ This function takes no effect on a single argument, even it's array-like.
1426
+ When there are both scalar and matrix arguments in `args`, the matrices
1427
+ must have the same shape, and scalars will be broadcasted to the same shape as the matrix.
1428
+
1429
+ Args:
1430
+ args: (List[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
1431
+ The input.
1432
+
1433
+ Returns:
1434
+ Minimum of the inputs.
1435
+
1436
+ Example::
1437
+
1438
+ >>> @ti.kernel
1439
+ >>> def foo():
1440
+ >>> x = ti.Vector([0, 1, 2])
1441
+ >>> y = ti.Vector([3, 4, 5])
1442
+ >>> z = ti.min(x, y, 1)
1443
+ >>> print(z) # [0, 1, 1]
1444
+ """
1445
+ num_args = len(args)
1446
+ assert num_args >= 1
1447
+ if num_args == 1:
1448
+ return args[0]
1449
+ if num_args == 2:
1450
+ return min_impl(args[0], args[1])
1451
+ return min_impl(args[0], min(*args[1:]))
1452
+
1453
+
1454
+ __all__ = [
1455
+ "acos",
1456
+ "asin",
1457
+ "atan2",
1458
+ "atomic_and",
1459
+ "atomic_or",
1460
+ "atomic_xor",
1461
+ "atomic_max",
1462
+ "atomic_sub",
1463
+ "atomic_min",
1464
+ "atomic_add",
1465
+ "atomic_mul",
1466
+ "bit_cast",
1467
+ "bit_shr",
1468
+ "cast",
1469
+ "ceil",
1470
+ "cos",
1471
+ "exp",
1472
+ "floor",
1473
+ "frexp",
1474
+ "log",
1475
+ "random",
1476
+ "raw_mod",
1477
+ "raw_div",
1478
+ "round",
1479
+ "rsqrt",
1480
+ "sin",
1481
+ "sqrt",
1482
+ "tan",
1483
+ "tanh",
1484
+ "max",
1485
+ "min",
1486
+ "select",
1487
+ "abs",
1488
+ "pow",
1489
+ ]