warp-lang 1.0.0b5__py3-none-manylinux2014_x86_64.whl → 1.0.0b6__py3-none-manylinux2014_x86_64.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 (187) hide show
  1. docs/conf.py +3 -4
  2. examples/env/env_ant.py +1 -1
  3. examples/env/env_cartpole.py +1 -1
  4. examples/env/env_humanoid.py +1 -1
  5. examples/example_dem.py +28 -26
  6. examples/example_diffray.py +37 -30
  7. examples/example_fluid.py +7 -3
  8. examples/example_jacobian_ik.py +1 -1
  9. examples/example_mesh_intersect.py +10 -7
  10. examples/example_nvdb.py +3 -3
  11. examples/example_render_opengl.py +19 -10
  12. examples/example_sim_cartpole.py +9 -5
  13. examples/example_sim_cloth.py +29 -25
  14. examples/example_sim_fk_grad.py +2 -2
  15. examples/example_sim_fk_grad_torch.py +3 -3
  16. examples/example_sim_grad_bounce.py +11 -8
  17. examples/example_sim_grad_cloth.py +12 -9
  18. examples/example_sim_granular.py +2 -2
  19. examples/example_sim_granular_collision_sdf.py +13 -13
  20. examples/example_sim_neo_hookean.py +3 -3
  21. examples/example_sim_particle_chain.py +2 -2
  22. examples/example_sim_quadruped.py +8 -5
  23. examples/example_sim_rigid_chain.py +8 -5
  24. examples/example_sim_rigid_contact.py +13 -10
  25. examples/example_sim_rigid_fem.py +2 -2
  26. examples/example_sim_rigid_gyroscopic.py +2 -2
  27. examples/example_sim_rigid_kinematics.py +1 -1
  28. examples/example_sim_trajopt.py +3 -2
  29. examples/fem/example_apic_fluid.py +5 -7
  30. examples/fem/example_diffusion_mgpu.py +18 -16
  31. warp/__init__.py +3 -2
  32. warp/bin/warp.so +0 -0
  33. warp/build_dll.py +29 -9
  34. warp/builtins.py +206 -7
  35. warp/codegen.py +58 -38
  36. warp/config.py +3 -1
  37. warp/context.py +234 -128
  38. warp/fem/__init__.py +2 -2
  39. warp/fem/cache.py +2 -1
  40. warp/fem/field/nodal_field.py +18 -17
  41. warp/fem/geometry/hexmesh.py +11 -6
  42. warp/fem/geometry/quadmesh_2d.py +16 -12
  43. warp/fem/geometry/tetmesh.py +19 -8
  44. warp/fem/geometry/trimesh_2d.py +18 -7
  45. warp/fem/integrate.py +341 -196
  46. warp/fem/quadrature/__init__.py +1 -1
  47. warp/fem/quadrature/pic_quadrature.py +138 -53
  48. warp/fem/quadrature/quadrature.py +81 -9
  49. warp/fem/space/__init__.py +1 -1
  50. warp/fem/space/basis_space.py +169 -51
  51. warp/fem/space/grid_2d_function_space.py +2 -2
  52. warp/fem/space/grid_3d_function_space.py +2 -2
  53. warp/fem/space/hexmesh_function_space.py +2 -2
  54. warp/fem/space/partition.py +9 -6
  55. warp/fem/space/quadmesh_2d_function_space.py +2 -2
  56. warp/fem/space/shape/cube_shape_function.py +27 -15
  57. warp/fem/space/shape/square_shape_function.py +29 -18
  58. warp/fem/space/tetmesh_function_space.py +2 -2
  59. warp/fem/space/topology.py +10 -0
  60. warp/fem/space/trimesh_2d_function_space.py +2 -2
  61. warp/fem/utils.py +10 -5
  62. warp/native/array.h +49 -8
  63. warp/native/builtin.h +31 -14
  64. warp/native/cuda_util.cpp +8 -3
  65. warp/native/cuda_util.h +1 -0
  66. warp/native/exports.h +1177 -1108
  67. warp/native/intersect.h +4 -4
  68. warp/native/intersect_adj.h +8 -8
  69. warp/native/mat.h +65 -6
  70. warp/native/mesh.h +126 -5
  71. warp/native/quat.h +28 -4
  72. warp/native/vec.h +76 -14
  73. warp/native/warp.cu +1 -6
  74. warp/render/render_opengl.py +261 -109
  75. warp/sim/import_mjcf.py +13 -7
  76. warp/sim/import_urdf.py +14 -14
  77. warp/sim/inertia.py +17 -18
  78. warp/sim/model.py +67 -67
  79. warp/sim/render.py +1 -1
  80. warp/sparse.py +6 -6
  81. warp/stubs.py +19 -81
  82. warp/tape.py +1 -1
  83. warp/tests/__main__.py +3 -6
  84. warp/tests/{test_class_kernel.py → aux_test_class_kernel.py} +9 -1
  85. warp/tests/aux_test_conditional_unequal_types_kernels.py +21 -0
  86. warp/tests/{test_dependent.py → aux_test_dependent.py} +2 -2
  87. warp/tests/{test_reference.py → aux_test_reference.py} +1 -1
  88. warp/tests/aux_test_unresolved_func.py +14 -0
  89. warp/tests/aux_test_unresolved_symbol.py +14 -0
  90. warp/tests/{test_kinematics.py → disabled_kinematics.py} +10 -12
  91. warp/tests/run_coverage_serial.py +31 -0
  92. warp/tests/test_adam.py +102 -106
  93. warp/tests/test_arithmetic.py +39 -40
  94. warp/tests/test_array.py +46 -48
  95. warp/tests/test_array_reduce.py +25 -19
  96. warp/tests/test_atomic.py +62 -26
  97. warp/tests/test_bool.py +16 -11
  98. warp/tests/test_builtins_resolution.py +1292 -0
  99. warp/tests/test_bvh.py +9 -12
  100. warp/tests/test_closest_point_edge_edge.py +53 -57
  101. warp/tests/test_codegen.py +164 -134
  102. warp/tests/test_compile_consts.py +13 -19
  103. warp/tests/test_conditional.py +30 -32
  104. warp/tests/test_copy.py +9 -12
  105. warp/tests/test_ctypes.py +90 -98
  106. warp/tests/test_dense.py +20 -14
  107. warp/tests/test_devices.py +34 -35
  108. warp/tests/test_dlpack.py +74 -75
  109. warp/tests/test_examples.py +215 -97
  110. warp/tests/test_fabricarray.py +15 -21
  111. warp/tests/test_fast_math.py +14 -11
  112. warp/tests/test_fem.py +280 -97
  113. warp/tests/test_fp16.py +19 -15
  114. warp/tests/test_func.py +177 -194
  115. warp/tests/test_generics.py +71 -77
  116. warp/tests/test_grad.py +83 -32
  117. warp/tests/test_grad_customs.py +7 -9
  118. warp/tests/test_hash_grid.py +6 -10
  119. warp/tests/test_import.py +9 -23
  120. warp/tests/test_indexedarray.py +19 -21
  121. warp/tests/test_intersect.py +15 -9
  122. warp/tests/test_large.py +17 -19
  123. warp/tests/test_launch.py +14 -17
  124. warp/tests/test_lerp.py +63 -63
  125. warp/tests/test_lvalue.py +84 -35
  126. warp/tests/test_marching_cubes.py +9 -13
  127. warp/tests/test_mat.py +388 -3004
  128. warp/tests/test_mat_lite.py +9 -12
  129. warp/tests/test_mat_scalar_ops.py +2889 -0
  130. warp/tests/test_math.py +10 -11
  131. warp/tests/test_matmul.py +104 -100
  132. warp/tests/test_matmul_lite.py +72 -98
  133. warp/tests/test_mesh.py +35 -32
  134. warp/tests/test_mesh_query_aabb.py +18 -25
  135. warp/tests/test_mesh_query_point.py +39 -23
  136. warp/tests/test_mesh_query_ray.py +9 -21
  137. warp/tests/test_mlp.py +8 -9
  138. warp/tests/test_model.py +89 -93
  139. warp/tests/test_modules_lite.py +15 -25
  140. warp/tests/test_multigpu.py +87 -114
  141. warp/tests/test_noise.py +10 -12
  142. warp/tests/test_operators.py +14 -21
  143. warp/tests/test_options.py +10 -11
  144. warp/tests/test_pinned.py +16 -18
  145. warp/tests/test_print.py +16 -20
  146. warp/tests/test_quat.py +121 -88
  147. warp/tests/test_rand.py +12 -13
  148. warp/tests/test_reload.py +27 -32
  149. warp/tests/test_rounding.py +7 -10
  150. warp/tests/test_runlength_encode.py +105 -106
  151. warp/tests/test_smoothstep.py +8 -9
  152. warp/tests/test_snippet.py +13 -22
  153. warp/tests/test_sparse.py +30 -29
  154. warp/tests/test_spatial.py +179 -174
  155. warp/tests/test_streams.py +100 -107
  156. warp/tests/test_struct.py +98 -67
  157. warp/tests/test_tape.py +11 -17
  158. warp/tests/test_torch.py +89 -86
  159. warp/tests/test_transient_module.py +9 -12
  160. warp/tests/test_types.py +328 -50
  161. warp/tests/test_utils.py +217 -218
  162. warp/tests/test_vec.py +133 -2133
  163. warp/tests/test_vec_lite.py +8 -11
  164. warp/tests/test_vec_scalar_ops.py +2099 -0
  165. warp/tests/test_volume.py +391 -382
  166. warp/tests/test_volume_write.py +122 -135
  167. warp/tests/unittest_serial.py +35 -0
  168. warp/tests/unittest_suites.py +291 -0
  169. warp/tests/{test_base.py → unittest_utils.py} +138 -25
  170. warp/tests/{test_misc.py → unused_test_misc.py} +13 -5
  171. warp/tests/{test_debug.py → walkthough_debug.py} +2 -15
  172. warp/thirdparty/unittest_parallel.py +257 -54
  173. warp/types.py +119 -98
  174. warp/utils.py +14 -0
  175. {warp_lang-1.0.0b5.dist-info → warp_lang-1.0.0b6.dist-info}/METADATA +2 -1
  176. {warp_lang-1.0.0b5.dist-info → warp_lang-1.0.0b6.dist-info}/RECORD +182 -178
  177. {warp_lang-1.0.0b5.dist-info → warp_lang-1.0.0b6.dist-info}/WHEEL +1 -1
  178. warp/tests/test_all.py +0 -239
  179. warp/tests/test_conditional_unequal_types_kernels.py +0 -14
  180. warp/tests/test_coverage.py +0 -38
  181. warp/tests/test_unresolved_func.py +0 -7
  182. warp/tests/test_unresolved_symbol.py +0 -7
  183. /warp/tests/{test_compile_consts_dummy.py → aux_test_compile_consts_dummy.py} +0 -0
  184. /warp/tests/{test_reference_reference.py → aux_test_reference_reference.py} +0 -0
  185. /warp/tests/{test_square.py → aux_test_square.py} +0 -0
  186. {warp_lang-1.0.0b5.dist-info → warp_lang-1.0.0b6.dist-info}/LICENSE.md +0 -0
  187. {warp_lang-1.0.0b5.dist-info → warp_lang-1.0.0b6.dist-info}/top_level.txt +0 -0
warp/tests/test_utils.py CHANGED
@@ -6,36 +6,15 @@
6
6
  # license agreement from NVIDIA CORPORATION is strictly prohibited.
7
7
 
8
8
  import contextlib
9
- import io
10
9
  import inspect
10
+ import io
11
11
  import unittest
12
12
 
13
- from warp.tests.test_base import *
14
-
13
+ from warp.tests.unittest_utils import *
15
14
 
16
15
  wp.init()
17
16
 
18
17
 
19
- def test_warn(test, device):
20
- with contextlib.redirect_stdout(io.StringIO()) as f:
21
- frame_info = inspect.getframeinfo(inspect.currentframe())
22
- wp.utils.warn("hello, world!")
23
-
24
- expected = '{}:{}: UserWarning: hello, world!\n wp.utils.warn("hello, world!")\n'.format(
25
- frame_info.filename,
26
- frame_info.lineno + 1,
27
- )
28
- test.assertEqual(f.getvalue(), expected)
29
-
30
-
31
- def test_transform_expand(test, device):
32
- t = (1.0, 2.0, 3.0, 4.0, 3.0, 2.0, 1.0)
33
- test.assertEqual(
34
- wp.utils.transform_expand(t),
35
- wp.transformf(p=(1.0, 2.0, 3.0), q=(4.0, 3.0, 2.0, 1.0)),
36
- )
37
-
38
-
39
18
  def test_array_scan(test, device):
40
19
  rng = np.random.default_rng(123)
41
20
 
@@ -71,19 +50,9 @@ def test_array_scan_empty(test, device):
71
50
  wp.utils.array_scan(values, result)
72
51
 
73
52
 
74
- def test_array_scan_error_devices_mismatch(test, device):
75
- values = wp.zeros(123, dtype=int, device="cpu")
76
- result = wp.zeros_like(values, device="cuda:0")
77
- with test.assertRaisesRegex(
78
- RuntimeError,
79
- r"Array storage devices do not match$",
80
- ):
81
- wp.utils.array_scan(values, result, True)
82
-
83
-
84
53
  def test_array_scan_error_sizes_mismatch(test, device):
85
- values = wp.zeros(123, dtype=int, device="cpu")
86
- result = wp.zeros(234, dtype=int, device="cpu")
54
+ values = wp.zeros(123, dtype=int, device=device)
55
+ result = wp.zeros(234, dtype=int, device=device)
87
56
  with test.assertRaisesRegex(
88
57
  RuntimeError,
89
58
  r"Array storage sizes do not match$",
@@ -92,8 +61,8 @@ def test_array_scan_error_sizes_mismatch(test, device):
92
61
 
93
62
 
94
63
  def test_array_scan_error_dtypes_mismatch(test, device):
95
- values = wp.zeros(123, dtype=int, device="cpu")
96
- result = wp.zeros(123, dtype=float, device="cpu")
64
+ values = wp.zeros(123, dtype=int, device=device)
65
+ result = wp.zeros(123, dtype=float, device=device)
97
66
  with test.assertRaisesRegex(
98
67
  RuntimeError,
99
68
  r"Array data types do not match$",
@@ -125,19 +94,9 @@ def test_radix_sort_pairs_empty(test, device):
125
94
  wp.utils.radix_sort_pairs(keys, values, 0)
126
95
 
127
96
 
128
- def test_radix_sort_pairs_error_devices_mismatch(test, device):
129
- keys = wp.array((1, 2, 3), dtype=int, device="cpu")
130
- values = wp.array((1, 2, 3), dtype=int, device="cuda:0")
131
- with test.assertRaisesRegex(
132
- RuntimeError,
133
- r"Array storage devices do not match$",
134
- ):
135
- wp.utils.radix_sort_pairs(keys, values, 1)
136
-
137
-
138
97
  def test_radix_sort_pairs_error_insufficient_storage(test, device):
139
- keys = wp.array((1, 2, 3), dtype=int, device="cpu")
140
- values = wp.array((1, 2, 3), dtype=int, device="cpu")
98
+ keys = wp.array((1, 2, 3), dtype=int, device=device)
99
+ values = wp.array((1, 2, 3), dtype=int, device=device)
141
100
  with test.assertRaisesRegex(
142
101
  RuntimeError,
143
102
  r"Array storage must be large enough to contain 2\*count elements$",
@@ -157,28 +116,19 @@ def test_radix_sort_pairs_error_unsupported_dtype(test, device):
157
116
 
158
117
  def test_array_sum(test, device):
159
118
  for dtype in (wp.float32, wp.float64):
160
- values = wp.array((1.0, 2.0, 3.0), dtype=dtype, device=device)
161
- test.assertEqual(wp.utils.array_sum(values), 6.0)
162
-
163
- values = wp.array((1.0, 2.0, 3.0), dtype=dtype, device=device)
164
- result = wp.empty(shape=(1,), dtype=dtype, device=device)
165
- wp.utils.array_sum(values, out=result)
166
- test.assertEqual(result.numpy()[0], 6.0)
167
-
119
+ with test.subTest(dtype=dtype):
120
+ values = wp.array((1.0, 2.0, 3.0), dtype=dtype, device=device)
121
+ test.assertEqual(wp.utils.array_sum(values), 6.0)
168
122
 
169
- def test_array_sum_error_out_device_mismatch(test, device):
170
- values = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device="cpu")
171
- result = wp.empty(shape=(1,), dtype=wp.float32, device="cuda:0")
172
- with test.assertRaisesRegex(
173
- RuntimeError,
174
- r"out storage device should match values array$",
175
- ):
176
- wp.utils.array_sum(values, out=result)
123
+ values = wp.array((1.0, 2.0, 3.0), dtype=dtype, device=device)
124
+ result = wp.empty(shape=(1,), dtype=dtype, device=device)
125
+ wp.utils.array_sum(values, out=result)
126
+ test.assertEqual(result.numpy()[0], 6.0)
177
127
 
178
128
 
179
129
  def test_array_sum_error_out_dtype_mismatch(test, device):
180
- values = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device="cpu")
181
- result = wp.empty(shape=(1,), dtype=wp.float64, device="cpu")
130
+ values = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device=device)
131
+ result = wp.empty(shape=(1,), dtype=wp.float64, device=device)
182
132
  with test.assertRaisesRegex(
183
133
  RuntimeError,
184
134
  r"out array should have type float32$",
@@ -187,8 +137,8 @@ def test_array_sum_error_out_dtype_mismatch(test, device):
187
137
 
188
138
 
189
139
  def test_array_sum_error_out_shape_mismatch(test, device):
190
- values = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device="cpu")
191
- result = wp.empty(shape=(2,), dtype=wp.float32, device="cpu")
140
+ values = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device=device)
141
+ result = wp.empty(shape=(2,), dtype=wp.float32, device=device)
192
142
  with test.assertRaisesRegex(
193
143
  RuntimeError,
194
144
  r"out array should have shape \(1,\)$",
@@ -219,8 +169,8 @@ def test_array_inner(test, device):
219
169
 
220
170
 
221
171
  def test_array_inner_error_sizes_mismatch(test, device):
222
- a = wp.array((1.0, 2.0), dtype=wp.float32, device="cpu")
223
- b = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device="cpu")
172
+ a = wp.array((1.0, 2.0), dtype=wp.float32, device=device)
173
+ b = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device=device)
224
174
  with test.assertRaisesRegex(
225
175
  RuntimeError,
226
176
  r"Array storage sizes do not match$",
@@ -228,19 +178,9 @@ def test_array_inner_error_sizes_mismatch(test, device):
228
178
  wp.utils.array_inner(a, b)
229
179
 
230
180
 
231
- def test_array_inner_error_devices_mismatch(test, device):
232
- a = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device="cpu")
233
- b = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device="cuda:0")
234
- with test.assertRaisesRegex(
235
- RuntimeError,
236
- r"Array storage devices do not match$",
237
- ):
238
- wp.utils.array_inner(a, b)
239
-
240
-
241
181
  def test_array_inner_error_dtypes_mismatch(test, device):
242
- a = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device="cpu")
243
- b = wp.array((1.0, 2.0, 3.0), dtype=wp.float64, device="cpu")
182
+ a = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device=device)
183
+ b = wp.array((1.0, 2.0, 3.0), dtype=wp.float64, device=device)
244
184
  with test.assertRaisesRegex(
245
185
  RuntimeError,
246
186
  r"Array data types do not match$",
@@ -248,21 +188,10 @@ def test_array_inner_error_dtypes_mismatch(test, device):
248
188
  wp.utils.array_inner(a, b)
249
189
 
250
190
 
251
- def test_array_inner_error_out_device_mismatch(test, device):
252
- a = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device="cpu")
253
- b = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device="cpu")
254
- result = wp.empty(shape=(1,), dtype=wp.float32, device="cuda:0")
255
- with test.assertRaisesRegex(
256
- RuntimeError,
257
- r"out storage device should match values array$",
258
- ):
259
- wp.utils.array_inner(a, b, result)
260
-
261
-
262
191
  def test_array_inner_error_out_dtype_mismatch(test, device):
263
- a = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device="cpu")
264
- b = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device="cpu")
265
- result = wp.empty(shape=(1,), dtype=wp.float64, device="cpu")
192
+ a = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device=device)
193
+ b = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device=device)
194
+ result = wp.empty(shape=(1,), dtype=wp.float64, device=device)
266
195
  with test.assertRaisesRegex(
267
196
  RuntimeError,
268
197
  r"out array should have type float32$",
@@ -271,9 +200,9 @@ def test_array_inner_error_out_dtype_mismatch(test, device):
271
200
 
272
201
 
273
202
  def test_array_inner_error_out_shape_mismatch(test, device):
274
- a = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device="cpu")
275
- b = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device="cpu")
276
- result = wp.empty(shape=(2,), dtype=wp.float32, device="cpu")
203
+ a = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device=device)
204
+ b = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device=device)
205
+ result = wp.empty(shape=(2,), dtype=wp.float32, device=device)
277
206
  with test.assertRaisesRegex(
278
207
  RuntimeError,
279
208
  r"out array should have shape \(1,\)$",
@@ -313,27 +242,17 @@ def test_array_cast(test, device):
313
242
  test.assertEqual(result.shape, (2,))
314
243
  assert_np_equal(result.numpy(), np.array((1.0, 2.0), dtype=float))
315
244
 
316
- values = wp.array(((1, 2), (3, 4)), dtype=int, device="cpu")
317
- result = wp.zeros((2, 2), dtype=int, device="cpu")
245
+ values = wp.array(((1, 2), (3, 4)), dtype=int, device=device)
246
+ result = wp.zeros((2, 2), dtype=int, device=device)
318
247
  wp.utils.array_cast(values, result)
319
248
  test.assertEqual(result.dtype, wp.int32)
320
249
  test.assertEqual(result.shape, (2, 2))
321
250
  assert_np_equal(result.numpy(), np.array(((1, 2), (3, 4)), dtype=int))
322
251
 
323
252
 
324
- def test_array_cast_error_devices_mismatch(test, device):
325
- values = wp.array((1, 2, 3), dtype=int, device="cpu")
326
- result = wp.empty(3, dtype=float, device="cuda:0")
327
- with test.assertRaisesRegex(
328
- RuntimeError,
329
- r"Array storage devices do not match$",
330
- ):
331
- wp.utils.array_cast(values, result)
332
-
333
-
334
253
  def test_array_cast_error_unsupported_partial_cast(test, device):
335
- values = wp.array(((1, 2), (3, 4)), dtype=int, device="cpu")
336
- result = wp.zeros((2, 2), dtype=float, device="cpu")
254
+ values = wp.array(((1, 2), (3, 4)), dtype=int, device=device)
255
+ result = wp.zeros((2, 2), dtype=float, device=device)
337
256
  with test.assertRaisesRegex(
338
257
  RuntimeError,
339
258
  r"Partial cast is not supported for arrays with more than one dimension$",
@@ -341,112 +260,192 @@ def test_array_cast_error_unsupported_partial_cast(test, device):
341
260
  wp.utils.array_cast(values, result, count=1)
342
261
 
343
262
 
344
- def test_mesh_adjacency(test, device):
345
- triangles = (
346
- (0, 3, 1),
347
- (0, 2, 3),
348
- )
349
- adj = wp.utils.MeshAdjacency(triangles, len(triangles))
350
- expected_edges = {
351
- (0, 3): (0, 3, 1, 2, 0, 1),
352
- (1, 3): (3, 1, 0, -1, 0, -1),
353
- (0, 1): (1, 0, 3, -1, 0, -1),
354
- (0, 2): (0, 2, 3, -1, 1, -1),
355
- (2, 3): (2, 3, 0, -1, 1, -1),
356
- }
357
- edges = {k: (e.v0, e.v1, e.o0, e.o1, e.f0, e.f1) for k, e in adj.edges.items()}
358
- test.assertDictEqual(edges, expected_edges)
359
-
360
-
361
- def test_mesh_adjacency_error_manifold(test, device):
362
- triangles = (
363
- (0, 3, 1),
364
- (0, 2, 3),
365
- (3, 0, 1),
366
- )
367
-
368
- with contextlib.redirect_stdout(io.StringIO()) as f:
369
- wp.utils.MeshAdjacency(triangles, len(triangles))
370
-
371
- test.assertEqual(f.getvalue(), "Detected non-manifold edge\n")
372
-
373
-
374
- def test_scoped_timer(test, device):
375
- with contextlib.redirect_stdout(io.StringIO()) as f:
376
- with wp.ScopedTimer("hello"):
377
- pass
378
-
379
- test.assertRegex(f.getvalue(), r"^hello took \d+\.\d+ ms$")
380
-
381
- with contextlib.redirect_stdout(io.StringIO()) as f:
382
- with wp.ScopedTimer("hello", detailed=True):
383
- pass
384
-
385
- test.assertRegex(f.getvalue(), r"^ 2 function calls in \d+\.\d+ seconds")
386
- test.assertRegex(f.getvalue(), r"hello took \d+\.\d+ ms$")
387
-
388
-
389
- def register(parent):
390
- devices = get_test_devices()
391
-
392
- class TestUtils(parent):
393
- pass
394
-
395
- add_function_test(TestUtils, "test_warn", test_warn)
396
- add_function_test(TestUtils, "test_transform_expand", test_transform_expand)
397
- add_function_test(TestUtils, "test_array_scan", test_array_scan, devices=devices)
398
- add_function_test(TestUtils, "test_array_scan_empty", test_array_scan_empty, devices=devices)
399
- add_function_test(TestUtils, "test_array_scan_error_devices_mismatch", test_array_scan_error_devices_mismatch)
400
- add_function_test(TestUtils, "test_array_scan_error_sizes_mismatch", test_array_scan_error_sizes_mismatch)
401
- add_function_test(TestUtils, "test_array_scan_error_dtypes_mismatch", test_array_scan_error_dtypes_mismatch)
402
- add_function_test(
403
- TestUtils, "test_array_scan_error_unsupported_dtype", test_array_scan_error_unsupported_dtype, devices=devices
404
- )
405
- add_function_test(TestUtils, "test_radix_sort_pairs", test_radix_sort_pairs, devices=devices)
406
- add_function_test(TestUtils, "test_radix_sort_pairs_empty", test_radix_sort_pairs_empty, devices=devices)
407
- add_function_test(
408
- TestUtils, "test_radix_sort_pairs_error_devices_mismatch", test_radix_sort_pairs_error_devices_mismatch
409
- )
410
- add_function_test(
411
- TestUtils, "test_radix_sort_pairs_error_insufficient_storage", test_radix_sort_pairs_error_insufficient_storage
412
- )
413
- add_function_test(
414
- TestUtils,
415
- "test_radix_sort_pairs_error_unsupported_dtype",
416
- test_radix_sort_pairs_error_unsupported_dtype,
417
- devices=devices,
418
- )
419
- add_function_test(TestUtils, "test_array_sum", test_array_sum, devices=devices)
420
- add_function_test(TestUtils, "test_array_sum_error_out_device_mismatch", test_array_sum_error_out_device_mismatch)
421
- add_function_test(TestUtils, "test_array_sum_error_out_dtype_mismatch", test_array_sum_error_out_dtype_mismatch)
422
- add_function_test(TestUtils, "test_array_sum_error_out_shape_mismatch", test_array_sum_error_out_shape_mismatch)
423
- add_function_test(
424
- TestUtils, "test_array_sum_error_unsupported_dtype", test_array_sum_error_unsupported_dtype, devices=devices
425
- )
426
- add_function_test(TestUtils, "test_array_inner", test_array_inner, devices=devices)
427
- add_function_test(TestUtils, "test_array_inner_error_sizes_mismatch", test_array_inner_error_sizes_mismatch)
428
- add_function_test(TestUtils, "test_array_inner_error_devices_mismatch", test_array_inner_error_devices_mismatch)
429
- add_function_test(TestUtils, "test_array_inner_error_dtypes_mismatch", test_array_inner_error_dtypes_mismatch)
430
- add_function_test(
431
- TestUtils, "test_array_inner_error_out_device_mismatch", test_array_inner_error_out_device_mismatch
432
- )
433
- add_function_test(TestUtils, "test_array_inner_error_out_dtype_mismatch", test_array_inner_error_out_dtype_mismatch)
434
- add_function_test(TestUtils, "test_array_inner_error_out_shape_mismatch", test_array_inner_error_out_shape_mismatch)
435
- add_function_test(
436
- TestUtils, "test_array_inner_error_unsupported_dtype", test_array_inner_error_unsupported_dtype, devices=devices
437
- )
438
- add_function_test(TestUtils, "test_array_cast", test_array_cast, devices=devices)
439
- add_function_test(TestUtils, "test_array_cast_error_devices_mismatch", test_array_cast_error_devices_mismatch)
440
- add_function_test(
441
- TestUtils, "test_array_cast_error_unsupported_partial_cast", test_array_cast_error_unsupported_partial_cast
442
- )
443
- add_function_test(TestUtils, "test_mesh_adjacency", test_mesh_adjacency)
444
- add_function_test(TestUtils, "test_mesh_adjacency_error_manifold", test_mesh_adjacency_error_manifold)
445
- add_function_test(TestUtils, "test_scoped_timer", test_scoped_timer)
446
- return TestUtils
263
+ devices = get_test_devices()
264
+
265
+
266
+ class TestUtils(unittest.TestCase):
267
+ def test_warn(self):
268
+ with contextlib.redirect_stdout(io.StringIO()) as f:
269
+ frame_info = inspect.getframeinfo(inspect.currentframe())
270
+ wp.utils.warn("hello, world!")
271
+
272
+ expected = '{}:{}: UserWarning: hello, world!\n wp.utils.warn("hello, world!")\n'.format(
273
+ frame_info.filename,
274
+ frame_info.lineno + 1,
275
+ )
276
+ self.assertEqual(f.getvalue(), expected)
277
+
278
+ def test_transform_expand(self):
279
+ t = (1.0, 2.0, 3.0, 4.0, 3.0, 2.0, 1.0)
280
+ self.assertEqual(
281
+ wp.utils.transform_expand(t),
282
+ wp.transformf(p=(1.0, 2.0, 3.0), q=(4.0, 3.0, 2.0, 1.0)),
283
+ )
284
+
285
+ @unittest.skipUnless(wp.is_cuda_available(), "Requires CUDA")
286
+ def test_array_scan_error_devices_mismatch(self):
287
+ values = wp.zeros(123, dtype=int, device="cpu")
288
+ result = wp.zeros_like(values, device="cuda:0")
289
+ with self.assertRaisesRegex(
290
+ RuntimeError,
291
+ r"Array storage devices do not match$",
292
+ ):
293
+ wp.utils.array_scan(values, result, True)
294
+
295
+ @unittest.skipUnless(wp.is_cuda_available(), "Requires CUDA")
296
+ def test_radix_sort_pairs_error_devices_mismatch(self):
297
+ keys = wp.array((1, 2, 3), dtype=int, device="cpu")
298
+ values = wp.array((1, 2, 3), dtype=int, device="cuda:0")
299
+ with self.assertRaisesRegex(
300
+ RuntimeError,
301
+ r"Array storage devices do not match$",
302
+ ):
303
+ wp.utils.radix_sort_pairs(keys, values, 1)
304
+
305
+ @unittest.skipUnless(wp.is_cuda_available(), "Requires CUDA")
306
+ def test_array_inner_error_out_device_mismatch(self):
307
+ a = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device="cpu")
308
+ b = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device="cpu")
309
+ result = wp.empty(shape=(1,), dtype=wp.float32, device="cuda:0")
310
+ with self.assertRaisesRegex(
311
+ RuntimeError,
312
+ r"out storage device should match values array$",
313
+ ):
314
+ wp.utils.array_inner(a, b, result)
315
+
316
+ @unittest.skipUnless(wp.is_cuda_available(), "Requires CUDA")
317
+ def test_array_sum_error_out_device_mismatch(self):
318
+ values = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device="cpu")
319
+ result = wp.empty(shape=(1,), dtype=wp.float32, device="cuda:0")
320
+ with self.assertRaisesRegex(
321
+ RuntimeError,
322
+ r"out storage device should match values array$",
323
+ ):
324
+ wp.utils.array_sum(values, out=result)
325
+
326
+ @unittest.skipUnless(wp.is_cuda_available(), "Requires CUDA")
327
+ def test_array_inner_error_devices_mismatch(self):
328
+ a = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device="cpu")
329
+ b = wp.array((1.0, 2.0, 3.0), dtype=wp.float32, device="cuda:0")
330
+ with self.assertRaisesRegex(
331
+ RuntimeError,
332
+ r"Array storage devices do not match$",
333
+ ):
334
+ wp.utils.array_inner(a, b)
335
+
336
+ @unittest.skipUnless(wp.is_cuda_available(), "Requires CUDA")
337
+ def test_array_cast_error_devices_mismatch(self):
338
+ values = wp.array((1, 2, 3), dtype=int, device="cpu")
339
+ result = wp.empty(3, dtype=float, device="cuda:0")
340
+ with self.assertRaisesRegex(
341
+ RuntimeError,
342
+ r"Array storage devices do not match$",
343
+ ):
344
+ wp.utils.array_cast(values, result)
345
+
346
+ def test_mesh_adjacency(self):
347
+ triangles = (
348
+ (0, 3, 1),
349
+ (0, 2, 3),
350
+ )
351
+ adj = wp.utils.MeshAdjacency(triangles, len(triangles))
352
+ expected_edges = {
353
+ (0, 3): (0, 3, 1, 2, 0, 1),
354
+ (1, 3): (3, 1, 0, -1, 0, -1),
355
+ (0, 1): (1, 0, 3, -1, 0, -1),
356
+ (0, 2): (0, 2, 3, -1, 1, -1),
357
+ (2, 3): (2, 3, 0, -1, 1, -1),
358
+ }
359
+ edges = {k: (e.v0, e.v1, e.o0, e.o1, e.f0, e.f1) for k, e in adj.edges.items()}
360
+ self.assertDictEqual(edges, expected_edges)
361
+
362
+ def test_mesh_adjacency_error_manifold(self):
363
+ triangles = (
364
+ (0, 3, 1),
365
+ (0, 2, 3),
366
+ (3, 0, 1),
367
+ )
368
+
369
+ with contextlib.redirect_stdout(io.StringIO()) as f:
370
+ wp.utils.MeshAdjacency(triangles, len(triangles))
371
+
372
+ self.assertEqual(f.getvalue(), "Detected non-manifold edge\n")
373
+
374
+ def test_scoped_timer(self):
375
+ with contextlib.redirect_stdout(io.StringIO()) as f:
376
+ with wp.ScopedTimer("hello"):
377
+ pass
378
+
379
+ self.assertRegex(f.getvalue(), r"^hello took \d+\.\d+ ms$")
380
+
381
+ with contextlib.redirect_stdout(io.StringIO()) as f:
382
+ with wp.ScopedTimer("hello", detailed=True):
383
+ pass
384
+
385
+ self.assertRegex(f.getvalue(), r"^ 2 function calls in \d+\.\d+ seconds")
386
+ self.assertRegex(f.getvalue(), r"hello took \d+\.\d+ ms$")
387
+
388
+
389
+ add_function_test(TestUtils, "test_array_scan", test_array_scan, devices=devices)
390
+ add_function_test(TestUtils, "test_array_scan_empty", test_array_scan_empty, devices=devices)
391
+ add_function_test(
392
+ TestUtils, "test_array_scan_error_sizes_mismatch", test_array_scan_error_sizes_mismatch, devices=devices
393
+ )
394
+ add_function_test(
395
+ TestUtils, "test_array_scan_error_dtypes_mismatch", test_array_scan_error_dtypes_mismatch, devices=devices
396
+ )
397
+ add_function_test(
398
+ TestUtils, "test_array_scan_error_unsupported_dtype", test_array_scan_error_unsupported_dtype, devices=devices
399
+ )
400
+ add_function_test(TestUtils, "test_radix_sort_pairs", test_radix_sort_pairs, devices=devices)
401
+ add_function_test(TestUtils, "test_radix_sort_pairs_empty", test_radix_sort_pairs, devices=devices)
402
+ add_function_test(
403
+ TestUtils,
404
+ "test_radix_sort_pairs_error_insufficient_storage",
405
+ test_radix_sort_pairs_error_insufficient_storage,
406
+ devices=devices,
407
+ )
408
+ add_function_test(
409
+ TestUtils,
410
+ "test_radix_sort_pairs_error_unsupported_dtype",
411
+ test_radix_sort_pairs_error_unsupported_dtype,
412
+ devices=devices,
413
+ )
414
+ add_function_test(TestUtils, "test_array_sum", test_array_sum, devices=devices)
415
+ add_function_test(
416
+ TestUtils, "test_array_sum_error_out_dtype_mismatch", test_array_sum_error_out_dtype_mismatch, devices=devices
417
+ )
418
+ add_function_test(
419
+ TestUtils, "test_array_sum_error_out_shape_mismatch", test_array_sum_error_out_shape_mismatch, devices=devices
420
+ )
421
+ add_function_test(
422
+ TestUtils, "test_array_sum_error_unsupported_dtype", test_array_sum_error_unsupported_dtype, devices=devices
423
+ )
424
+ add_function_test(TestUtils, "test_array_inner", test_array_inner, devices=devices)
425
+ add_function_test(
426
+ TestUtils, "test_array_inner_error_sizes_mismatch", test_array_inner_error_sizes_mismatch, devices=devices
427
+ )
428
+ add_function_test(
429
+ TestUtils, "test_array_inner_error_dtypes_mismatch", test_array_inner_error_dtypes_mismatch, devices=devices
430
+ )
431
+ add_function_test(
432
+ TestUtils, "test_array_inner_error_out_dtype_mismatch", test_array_inner_error_out_dtype_mismatch, devices=devices
433
+ )
434
+ add_function_test(
435
+ TestUtils, "test_array_inner_error_out_shape_mismatch", test_array_inner_error_out_shape_mismatch, devices=devices
436
+ )
437
+ add_function_test(
438
+ TestUtils, "test_array_inner_error_unsupported_dtype", test_array_inner_error_unsupported_dtype, devices=devices
439
+ )
440
+ add_function_test(TestUtils, "test_array_cast", test_array_cast, devices=devices)
441
+ add_function_test(
442
+ TestUtils,
443
+ "test_array_cast_error_unsupported_partial_cast",
444
+ test_array_cast_error_unsupported_partial_cast,
445
+ devices=devices,
446
+ )
447
447
 
448
448
 
449
449
  if __name__ == "__main__":
450
450
  wp.build.clear_kernel_cache()
451
- _ = register(unittest.TestCase)
452
451
  unittest.main(verbosity=2)