warp-lang 1.8.1__py3-none-manylinux_2_34_aarch64.whl → 1.9.0__py3-none-manylinux_2_34_aarch64.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.

Potentially problematic release.


This version of warp-lang might be problematic. Click here for more details.

Files changed (134) hide show
  1. warp/__init__.py +282 -103
  2. warp/__init__.pyi +482 -110
  3. warp/bin/warp-clang.so +0 -0
  4. warp/bin/warp.so +0 -0
  5. warp/build.py +93 -30
  6. warp/build_dll.py +47 -67
  7. warp/builtins.py +955 -137
  8. warp/codegen.py +312 -206
  9. warp/config.py +1 -1
  10. warp/context.py +1249 -784
  11. warp/examples/core/example_marching_cubes.py +1 -0
  12. warp/examples/core/example_render_opengl.py +100 -3
  13. warp/examples/fem/example_apic_fluid.py +98 -52
  14. warp/examples/fem/example_convection_diffusion_dg.py +25 -4
  15. warp/examples/fem/example_diffusion_mgpu.py +8 -3
  16. warp/examples/fem/utils.py +68 -22
  17. warp/fabric.py +1 -1
  18. warp/fem/cache.py +27 -19
  19. warp/fem/domain.py +2 -2
  20. warp/fem/field/nodal_field.py +2 -2
  21. warp/fem/field/virtual.py +264 -166
  22. warp/fem/geometry/geometry.py +5 -5
  23. warp/fem/integrate.py +129 -51
  24. warp/fem/space/restriction.py +4 -0
  25. warp/fem/space/shape/tet_shape_function.py +3 -10
  26. warp/jax_experimental/custom_call.py +1 -1
  27. warp/jax_experimental/ffi.py +2 -1
  28. warp/marching_cubes.py +708 -0
  29. warp/native/array.h +99 -4
  30. warp/native/builtin.h +82 -5
  31. warp/native/bvh.cpp +64 -28
  32. warp/native/bvh.cu +58 -58
  33. warp/native/bvh.h +2 -2
  34. warp/native/clang/clang.cpp +7 -7
  35. warp/native/coloring.cpp +8 -2
  36. warp/native/crt.cpp +2 -2
  37. warp/native/crt.h +3 -5
  38. warp/native/cuda_util.cpp +41 -10
  39. warp/native/cuda_util.h +10 -4
  40. warp/native/exports.h +1842 -1908
  41. warp/native/fabric.h +2 -1
  42. warp/native/hashgrid.cpp +37 -37
  43. warp/native/hashgrid.cu +2 -2
  44. warp/native/initializer_array.h +1 -1
  45. warp/native/intersect.h +2 -2
  46. warp/native/mat.h +1910 -116
  47. warp/native/mathdx.cpp +43 -43
  48. warp/native/mesh.cpp +24 -24
  49. warp/native/mesh.cu +26 -26
  50. warp/native/mesh.h +4 -2
  51. warp/native/nanovdb/GridHandle.h +179 -12
  52. warp/native/nanovdb/HostBuffer.h +8 -7
  53. warp/native/nanovdb/NanoVDB.h +517 -895
  54. warp/native/nanovdb/NodeManager.h +323 -0
  55. warp/native/nanovdb/PNanoVDB.h +2 -2
  56. warp/native/quat.h +331 -14
  57. warp/native/range.h +7 -1
  58. warp/native/reduce.cpp +10 -10
  59. warp/native/reduce.cu +13 -14
  60. warp/native/runlength_encode.cpp +2 -2
  61. warp/native/runlength_encode.cu +5 -5
  62. warp/native/scan.cpp +3 -3
  63. warp/native/scan.cu +4 -4
  64. warp/native/sort.cpp +10 -10
  65. warp/native/sort.cu +22 -22
  66. warp/native/sparse.cpp +8 -8
  67. warp/native/sparse.cu +13 -13
  68. warp/native/spatial.h +366 -17
  69. warp/native/temp_buffer.h +2 -2
  70. warp/native/tile.h +283 -69
  71. warp/native/vec.h +381 -14
  72. warp/native/volume.cpp +54 -54
  73. warp/native/volume.cu +1 -1
  74. warp/native/volume.h +2 -1
  75. warp/native/volume_builder.cu +30 -37
  76. warp/native/warp.cpp +150 -149
  77. warp/native/warp.cu +323 -192
  78. warp/native/warp.h +227 -226
  79. warp/optim/linear.py +736 -271
  80. warp/render/imgui_manager.py +289 -0
  81. warp/render/render_opengl.py +85 -6
  82. warp/sim/graph_coloring.py +2 -2
  83. warp/sparse.py +558 -175
  84. warp/tests/aux_test_module_aot.py +7 -0
  85. warp/tests/cuda/test_async.py +3 -3
  86. warp/tests/cuda/test_conditional_captures.py +101 -0
  87. warp/tests/geometry/test_marching_cubes.py +233 -12
  88. warp/tests/sim/test_coloring.py +6 -6
  89. warp/tests/test_array.py +56 -5
  90. warp/tests/test_codegen.py +3 -2
  91. warp/tests/test_context.py +8 -15
  92. warp/tests/test_enum.py +136 -0
  93. warp/tests/test_examples.py +2 -2
  94. warp/tests/test_fem.py +45 -2
  95. warp/tests/test_fixedarray.py +229 -0
  96. warp/tests/test_func.py +18 -15
  97. warp/tests/test_future_annotations.py +7 -5
  98. warp/tests/test_linear_solvers.py +30 -0
  99. warp/tests/test_map.py +1 -1
  100. warp/tests/test_mat.py +1518 -378
  101. warp/tests/test_mat_assign_copy.py +178 -0
  102. warp/tests/test_mat_constructors.py +574 -0
  103. warp/tests/test_module_aot.py +287 -0
  104. warp/tests/test_print.py +69 -0
  105. warp/tests/test_quat.py +140 -34
  106. warp/tests/test_quat_assign_copy.py +145 -0
  107. warp/tests/test_reload.py +2 -1
  108. warp/tests/test_sparse.py +71 -0
  109. warp/tests/test_spatial.py +140 -34
  110. warp/tests/test_spatial_assign_copy.py +160 -0
  111. warp/tests/test_struct.py +43 -3
  112. warp/tests/test_types.py +0 -20
  113. warp/tests/test_vec.py +179 -34
  114. warp/tests/test_vec_assign_copy.py +143 -0
  115. warp/tests/tile/test_tile.py +184 -18
  116. warp/tests/tile/test_tile_cholesky.py +605 -0
  117. warp/tests/tile/test_tile_load.py +169 -0
  118. warp/tests/tile/test_tile_mathdx.py +2 -558
  119. warp/tests/tile/test_tile_matmul.py +1 -1
  120. warp/tests/tile/test_tile_mlp.py +1 -1
  121. warp/tests/tile/test_tile_shared_memory.py +5 -5
  122. warp/tests/unittest_suites.py +6 -0
  123. warp/tests/walkthrough_debug.py +1 -1
  124. warp/thirdparty/unittest_parallel.py +108 -9
  125. warp/types.py +554 -264
  126. warp/utils.py +68 -86
  127. {warp_lang-1.8.1.dist-info → warp_lang-1.9.0.dist-info}/METADATA +28 -65
  128. {warp_lang-1.8.1.dist-info → warp_lang-1.9.0.dist-info}/RECORD +131 -121
  129. warp/native/marching.cpp +0 -19
  130. warp/native/marching.cu +0 -514
  131. warp/native/marching.h +0 -19
  132. {warp_lang-1.8.1.dist-info → warp_lang-1.9.0.dist-info}/WHEEL +0 -0
  133. {warp_lang-1.8.1.dist-info → warp_lang-1.9.0.dist-info}/licenses/LICENSE.md +0 -0
  134. {warp_lang-1.8.1.dist-info → warp_lang-1.9.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,145 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ import unittest
17
+
18
+ import numpy as np
19
+
20
+ import warp as wp
21
+ from warp.tests.unittest_utils import *
22
+
23
+
24
+ def setUpModule():
25
+ wp.config.enable_vector_component_overwrites = True
26
+
27
+
28
+ def tearDownModule():
29
+ wp.config.enable_vector_component_overwrites = False
30
+
31
+
32
+ @wp.kernel
33
+ def quat_assign_subscript(x: wp.array(dtype=float), y: wp.array(dtype=wp.quat)):
34
+ i = wp.tid()
35
+
36
+ a = wp.quat()
37
+ a[0] = 1.0 * x[i]
38
+ a[1] = 2.0 * x[i]
39
+ a[2] = 3.0 * x[i]
40
+ a[3] = 4.0 * x[i]
41
+ y[i] = a
42
+
43
+
44
+ @wp.kernel
45
+ def quat_assign_attribute(x: wp.array(dtype=float), y: wp.array(dtype=wp.quat)):
46
+ i = wp.tid()
47
+
48
+ a = wp.quat()
49
+ a.x = 1.0 * x[i]
50
+ a.y = 2.0 * x[i]
51
+ a.z = 3.0 * x[i]
52
+ a.w = 4.0 * x[i]
53
+ y[i] = a
54
+
55
+
56
+ def test_quat_assign(test, device):
57
+ def run(kernel):
58
+ x = wp.ones(1, dtype=float, requires_grad=True, device=device)
59
+ y = wp.zeros(1, dtype=wp.quat, requires_grad=True, device=device)
60
+
61
+ tape = wp.Tape()
62
+ with tape:
63
+ wp.launch(kernel, 1, inputs=[x], outputs=[y], device=device)
64
+
65
+ y.grad = wp.ones_like(y)
66
+ tape.backward()
67
+
68
+ assert_np_equal(y.numpy(), np.array([[1.0, 2.0, 3.0, 4.0]], dtype=float))
69
+ assert_np_equal(x.grad.numpy(), np.array([10.0], dtype=float))
70
+
71
+ run(quat_assign_subscript)
72
+ run(quat_assign_attribute)
73
+
74
+
75
+ def test_quat_assign_copy(test, device):
76
+ @wp.kernel(module="unique")
77
+ def quat_assign_overwrite(x: wp.array(dtype=wp.quat), y: wp.array(dtype=wp.quat)):
78
+ tid = wp.tid()
79
+
80
+ a = wp.quat()
81
+ b = x[tid]
82
+ a = b
83
+ a[1] = 3.0
84
+
85
+ y[tid] = a
86
+
87
+ x = wp.ones(1, dtype=wp.quat, device=device, requires_grad=True)
88
+ y = wp.zeros(1, dtype=wp.quat, device=device, requires_grad=True)
89
+
90
+ tape = wp.Tape()
91
+ with tape:
92
+ wp.launch(quat_assign_overwrite, dim=1, inputs=[x, y], device=device)
93
+
94
+ y.grad = wp.ones_like(y, requires_grad=False)
95
+ tape.backward()
96
+
97
+ assert_np_equal(y.numpy(), np.array([[1.0, 3.0, 1.0, 1.0]], dtype=float))
98
+ assert_np_equal(x.grad.numpy(), np.array([[1.0, 0.0, 1.0, 1.0]], dtype=float))
99
+
100
+
101
+ def test_quat_slicing_assign_backward(test, device):
102
+ @wp.kernel(module="unique")
103
+ def kernel(arr_x: wp.array(dtype=wp.vec2), arr_y: wp.array(dtype=wp.quat)):
104
+ i = wp.tid()
105
+
106
+ x = arr_x[i]
107
+ y = arr_y[i]
108
+
109
+ y[:2] = x
110
+ y[1:-1] += x[:2]
111
+ y[3:1:-1] -= x[0:]
112
+
113
+ arr_y[i] = y
114
+
115
+ x = wp.ones(1, dtype=wp.vec2, requires_grad=True, device=device)
116
+ y = wp.zeros(1, dtype=wp.quat, requires_grad=True, device=device)
117
+
118
+ tape = wp.Tape()
119
+ with tape:
120
+ wp.launch(kernel, 1, inputs=(x,), outputs=(y,), device=device)
121
+
122
+ y.grad = wp.ones_like(y)
123
+ tape.backward()
124
+
125
+ assert_np_equal(y.numpy(), np.array(((1.0, 2.0, 0.0, -1.0),), dtype=float))
126
+ assert_np_equal(x.grad.numpy(), np.array(((1.0, 1.0),), dtype=float))
127
+
128
+
129
+ devices = get_test_devices()
130
+
131
+
132
+ class TestQuatAssignCopy(unittest.TestCase):
133
+ pass
134
+
135
+
136
+ add_function_test(TestQuatAssignCopy, "test_quat_assign", test_quat_assign, devices=devices)
137
+ add_function_test(TestQuatAssignCopy, "test_quat_assign_copy", test_quat_assign_copy, devices=devices)
138
+ add_function_test(
139
+ TestQuatAssignCopy, "test_quat_slicing_assign_backward", test_quat_slicing_assign_backward, devices=devices
140
+ )
141
+
142
+
143
+ if __name__ == "__main__":
144
+ wp.clear_kernel_cache()
145
+ unittest.main(verbosity=2)
warp/tests/test_reload.py CHANGED
@@ -35,7 +35,8 @@ def reload_module(module):
35
35
  # Clearing the .pyc file associated with a module is a necessary workaround
36
36
  # for `importlib.reload` to work as expected when run from within Kit.
37
37
  cache_file = importlib.util.cache_from_source(module.__file__)
38
- os.remove(cache_file)
38
+ if os.path.exists(cache_file):
39
+ os.remove(cache_file)
39
40
  importlib.reload(module)
40
41
 
41
42
 
warp/tests/test_sparse.py CHANGED
@@ -568,6 +568,7 @@ def make_test_bsr_mv(block_shape, scalar_type):
568
568
  work_buffer = wp.empty_like(y)
569
569
  for alpha, beta in zip(alphas, betas):
570
570
  ref = alpha * _bsr_to_dense(A) @ x.numpy().flatten() + beta * y.numpy().flatten()
571
+
571
572
  if beta == 0.0:
572
573
  y = A @ x
573
574
  else:
@@ -604,7 +605,67 @@ def make_test_bsr_mv(block_shape, scalar_type):
604
605
  return test_bsr_mv
605
606
 
606
607
 
608
+ def make_test_bsr_multiply_deep(block_shape, scalar_type):
609
+ def test_bsr_multiply_deep(test, device):
610
+ """Test BSR matrix multiplication with deep matrices (many columns > 256)"""
611
+ rng = np.random.default_rng(123)
612
+
613
+ # Generate a dense matrix with few rows and many columns (> 256)
614
+ nrow = (4 + block_shape[0] - 1) // block_shape[0]
615
+ ncol = (600 + block_shape[1] - 1) // block_shape[1]
616
+
617
+ # Create a dense "sparse" matrix
618
+ values = rng.random(size=(nrow * ncol, block_shape[0], block_shape[1]))
619
+ rows, cols = np.meshgrid(np.arange(nrow), np.arange(ncol))
620
+
621
+ # Convert to warp arrays
622
+ rows = wp.array(rows.flatten(), dtype=int, device=device)
623
+ cols = wp.array(cols.flatten(), dtype=int, device=device)
624
+ vals = wp.array(values, dtype=scalar_type, device=device)
625
+
626
+ # Convert to BSR using bsr_from_triplets
627
+ A = bsr_from_triplets(nrow, ncol, rows, cols, vals)
628
+
629
+ # Get dense representation for numpy reference
630
+ A_dense = _bsr_to_dense(A)
631
+
632
+ # Multiply with itself transpose using bsr_mm
633
+ # A @ A.T should result in a nrow x nrow matrix
634
+ At = bsr_transposed(A)
635
+
636
+ result = bsr_mm(A, At)
637
+
638
+ # Check that the result is correct against numpy reference
639
+ result_dense = _bsr_to_dense(result)
640
+ ref_dense = A_dense @ A_dense.T
641
+
642
+ assert_np_equal(result_dense, ref_dense, 0.0001)
643
+
644
+ # Additional test: multiply A.T @ A (should be ncol x ncol)
645
+ result2 = bsr_mm(At, A)
646
+ result2_dense = _bsr_to_dense(result2)
647
+ ref2_dense = A_dense.T @ A_dense
648
+
649
+ assert_np_equal(result2_dense, ref2_dense, 0.0001)
650
+
651
+ # Test matrix vector products
652
+ x = wp.array(rng.random(size=A.shape[1]), dtype=A.scalar_type, device=device)
653
+ y = wp.array(rng.random(size=A.shape[0]), dtype=A.scalar_type, device=device)
654
+ bsr_mv(A, x, y)
655
+ res = y.numpy().flatten()
656
+ ref = A_dense @ x.numpy().flatten()
657
+ assert_np_equal(res, ref, 0.0001 * block_shape[1])
658
+
659
+ bsr_mv(A, y, x, transpose=True)
660
+ res = x.numpy().flatten()
661
+ ref = A_dense.T @ y.numpy().flatten()
662
+ assert_np_equal(res, ref, 0.0001 * block_shape[1])
663
+
664
+ return test_bsr_multiply_deep
665
+
666
+
607
667
  devices = get_test_devices()
668
+ cuda_test_devices = get_selected_cuda_test_devices()
608
669
 
609
670
 
610
671
  class TestSparse(unittest.TestCase):
@@ -653,6 +714,16 @@ add_function_test(TestSparse, "test_csr_mm", make_test_bsr_mm((1, 1), wp.float32
653
714
  add_function_test(TestSparse, "test_bsr_mm_1_3", make_test_bsr_mm((1, 3), wp.float32), devices=devices)
654
715
  add_function_test(TestSparse, "test_bsr_mm_3_3", make_test_bsr_mm((3, 3), wp.float64), devices=devices)
655
716
 
717
+ add_function_test(
718
+ TestSparse, "test_bsr_multiply_deep_2_2", make_test_bsr_multiply_deep((2, 2), wp.float64), devices=devices
719
+ )
720
+ add_function_test(
721
+ TestSparse,
722
+ "test_bsr_multiply_deep_30_30",
723
+ make_test_bsr_multiply_deep((30, 30), wp.float32),
724
+ devices=cuda_test_devices,
725
+ )
726
+
656
727
  add_function_test(TestSparse, "test_csr_mv", make_test_bsr_mv((1, 1), wp.float32), devices=devices)
657
728
  add_function_test(TestSparse, "test_bsr_mv_1_3", make_test_bsr_mv((1, 3), wp.float32), devices=devices)
658
729
  add_function_test(TestSparse, "test_bsr_mv_3_3", make_test_bsr_mv((3, 3), wp.float64), devices=devices)
@@ -2217,39 +2217,6 @@ def test_transform_assign(test, device):
2217
2217
  assert_np_equal(y.grad.numpy(), np.array([[1.0, 1.0, 1.0, 1.0]], dtype=float))
2218
2218
 
2219
2219
 
2220
- def test_transform_assign_copy(test, device):
2221
- saved_enable_vector_component_overwrites_setting = wp.config.enable_vector_component_overwrites
2222
- try:
2223
- wp.config.enable_vector_component_overwrites = True
2224
-
2225
- @wp.kernel
2226
- def transform_assign_overwrite(x: wp.array(dtype=wp.transform), y: wp.array(dtype=wp.transform)):
2227
- tid = wp.tid()
2228
-
2229
- a = wp.transform()
2230
- b = x[tid]
2231
- a = b
2232
- a[1] = 3.0
2233
-
2234
- y[tid] = a
2235
-
2236
- x = wp.ones(1, dtype=wp.transform, device=device, requires_grad=True)
2237
- y = wp.zeros(1, dtype=wp.transform, device=device, requires_grad=True)
2238
-
2239
- tape = wp.Tape()
2240
- with tape:
2241
- wp.launch(transform_assign_overwrite, dim=1, inputs=[x, y], device=device)
2242
-
2243
- y.grad = wp.ones_like(y, requires_grad=False)
2244
- tape.backward()
2245
-
2246
- assert_np_equal(y.numpy(), np.array([[1.0, 3.0, 1.0, 1.0, 1.0, 1.0, 1.0]], dtype=float))
2247
- assert_np_equal(x.grad.numpy(), np.array([[1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0]], dtype=float))
2248
-
2249
- finally:
2250
- wp.config.enable_vector_component_overwrites = saved_enable_vector_component_overwrites_setting
2251
-
2252
-
2253
2220
  @wp.kernel
2254
2221
  def transform_array_extract_subscript(x: wp.array2d(dtype=wp.transform), y: wp.array2d(dtype=float)):
2255
2222
  i, j = wp.tid()
@@ -2510,6 +2477,141 @@ def test_transform_array_sub_inplace(test, device):
2510
2477
  assert_np_equal(x.grad.numpy(), np.array([[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0]], dtype=float))
2511
2478
 
2512
2479
 
2480
+ def test_transform_indexing_assign(test, device):
2481
+ @wp.func
2482
+ def fn():
2483
+ t = wp.transform(p=wp.vec3(1.0, 2.0, 3.0), q=wp.quat(4.0, 5.0, 6.0, 7.0))
2484
+
2485
+ t[0] = 123.0
2486
+ t[3] *= 2.0
2487
+
2488
+ wp.expect_eq(t[0], 123.0)
2489
+ wp.expect_eq(t[1], 2.0)
2490
+ wp.expect_eq(t[2], 3.0)
2491
+ wp.expect_eq(t[3], 8.0)
2492
+ wp.expect_eq(t[4], 5.0)
2493
+ wp.expect_eq(t[5], 6.0)
2494
+ wp.expect_eq(t[6], 7.0)
2495
+
2496
+ t[-1] = 123.0
2497
+ t[-5] *= 2.0
2498
+
2499
+ wp.expect_eq(t[0], 123.0)
2500
+ wp.expect_eq(t[1], 2.0)
2501
+ wp.expect_eq(t[2], 6.0)
2502
+ wp.expect_eq(t[3], 8.0)
2503
+ wp.expect_eq(t[4], 5.0)
2504
+ wp.expect_eq(t[5], 6.0)
2505
+ wp.expect_eq(t[6], 123.0)
2506
+
2507
+ @wp.kernel(module="unique")
2508
+ def kernel():
2509
+ fn()
2510
+
2511
+ wp.launch(kernel, 1, device=device)
2512
+ wp.synchronize()
2513
+ fn()
2514
+
2515
+
2516
+ def test_transform_slicing_assign(test, device):
2517
+ vec0 = wp.vec(0, float)
2518
+ vec1 = wp.vec(1, float)
2519
+ vec2 = wp.vec(2, float)
2520
+ vec3 = wp.vec(3, float)
2521
+ vec4 = wp.vec(4, float)
2522
+ vec5 = wp.vec(5, float)
2523
+ vec6 = wp.vec(6, float)
2524
+ vec7 = wp.vec(7, float)
2525
+
2526
+ @wp.func
2527
+ def fn():
2528
+ t = wp.transform(p=wp.vec3(1.0, 2.0, 3.0), q=wp.quat(4.0, 5.0, 6.0, 7.0))
2529
+
2530
+ wp.expect_eq(t[:] == vec7(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0), True)
2531
+ wp.expect_eq(t[-123:123] == vec7(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0), True)
2532
+ wp.expect_eq(t[123:] == vec0(), True)
2533
+ wp.expect_eq(t[:-123] == vec0(), True)
2534
+ wp.expect_eq(t[::123] == vec1(1.0), True)
2535
+
2536
+ wp.expect_eq(t[1:] == vec6(2.0, 3.0, 4.0, 5.0, 6.0, 7.0), True)
2537
+ wp.expect_eq(t[-2:] == vec2(6.0, 7.0), True)
2538
+ wp.expect_eq(t[:2] == vec2(1.0, 2.0), True)
2539
+ wp.expect_eq(t[:-1] == vec6(1.0, 2.0, 3.0, 4.0, 5.0, 6.0), True)
2540
+ wp.expect_eq(t[::2] == vec4(1.0, 3.0, 5.0, 7.0), True)
2541
+ wp.expect_eq(t[1::2] == vec3(2.0, 4.0, 6.0), True)
2542
+ wp.expect_eq(t[::-1] == vec7(7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0), True)
2543
+ wp.expect_eq(t[::-2] == vec4(7.0, 5.0, 3.0, 1.0), True)
2544
+ wp.expect_eq(t[1::-2] == vec1(2.0), True)
2545
+
2546
+ t[1:] = vec6(8.0, 9.0, 10.0, 11.0, 12.0, 13.0)
2547
+ wp.expect_eq(t == wp.transform(p=wp.vec3(1.0, 8.0, 9.0), q=wp.quat(10.0, 11.0, 12.0, 13.0)), True)
2548
+
2549
+ t[-2:] = vec2(14.0, 15.0)
2550
+ wp.expect_eq(t == wp.transform(p=wp.vec3(1.0, 8.0, 9.0), q=wp.quat(10.0, 11.0, 14.0, 15.0)), True)
2551
+
2552
+ t[:2] = vec2(16.0, 17.0)
2553
+ wp.expect_eq(t == wp.transform(p=wp.vec3(16.0, 17.0, 9.0), q=wp.quat(10.0, 11.0, 14.0, 15.0)), True)
2554
+
2555
+ t[:-1] = vec6(18.0, 19.0, 20.0, 21.0, 22.0, 23.0)
2556
+ wp.expect_eq(t == wp.transform(p=wp.vec3(18.0, 19.0, 20.0), q=wp.quat(21.0, 22.0, 23.0, 15.0)), True)
2557
+
2558
+ t[::2] = vec4(24.0, 25.0, 26.0, 27.0)
2559
+ wp.expect_eq(t == wp.transform(p=wp.vec3(24.0, 19.0, 25.0), q=wp.quat(21.0, 26.0, 23.0, 27.0)), True)
2560
+
2561
+ t[1::2] = vec3(28.0, 29.0, 30.0)
2562
+ wp.expect_eq(t == wp.transform(p=wp.vec3(24.0, 28.0, 25.0), q=wp.quat(29.0, 26.0, 30.0, 27.0)), True)
2563
+
2564
+ t[::-1] = vec7(31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0)
2565
+ wp.expect_eq(t == wp.transform(p=wp.vec3(37.0, 36.0, 35.0), q=wp.quat(34.0, 33.0, 32.0, 31.0)), True)
2566
+
2567
+ t[::-2] = vec4(38.0, 39.0, 40.0, 41.0)
2568
+ wp.expect_eq(t == wp.transform(p=wp.vec3(41.0, 36.0, 40.0), q=wp.quat(34.0, 39.0, 32.0, 38.0)), True)
2569
+
2570
+ t[1::-2] = vec1(42.0)
2571
+ wp.expect_eq(t == wp.transform(p=wp.vec3(41.0, 42.0, 40.0), q=wp.quat(34.0, 39.0, 32.0, 38.0)), True)
2572
+
2573
+ t[1:] += vec6(43.0, 44.0, 45.0, 46.0, 47.0, 48.0)
2574
+ wp.expect_eq(t == wp.transform(p=wp.vec3(41.0, 85.0, 84.0), q=wp.quat(79.0, 85.0, 79.0, 86.0)), True)
2575
+
2576
+ t[:-1] -= vec6(49.0, 50.0, 51.0, 52.0, 53.0, 54.0)
2577
+ wp.expect_eq(t == wp.transform(p=wp.vec3(-8.0, 35.0, 33.0), q=wp.quat(27.0, 32.0, 25.0, 86.0)), True)
2578
+
2579
+ @wp.kernel(module="unique")
2580
+ def kernel():
2581
+ fn()
2582
+
2583
+ wp.launch(kernel, 1, device=device)
2584
+ wp.synchronize()
2585
+ fn()
2586
+
2587
+
2588
+ def test_transform_slicing_assign_backward(test, device):
2589
+ @wp.kernel(module="unique")
2590
+ def kernel(arr_x: wp.array(dtype=wp.vec2), arr_y: wp.array(dtype=wp.transform)):
2591
+ i = wp.tid()
2592
+
2593
+ y = arr_y[i]
2594
+
2595
+ y[:2] = arr_x[i]
2596
+ y[1:-4] += arr_x[i][:2]
2597
+ y[3:1:-1] -= arr_x[i][0:]
2598
+
2599
+ arr_y[i] = y
2600
+
2601
+ x = wp.ones(1, dtype=wp.vec2, requires_grad=True, device=device)
2602
+ y = wp.zeros(1, dtype=wp.transform, requires_grad=True, device=device)
2603
+
2604
+ tape = wp.Tape()
2605
+ with tape:
2606
+ wp.launch(kernel, 1, inputs=(x,), outputs=(y,), device=device)
2607
+
2608
+ y.grad = wp.ones_like(y)
2609
+ tape.backward()
2610
+
2611
+ assert_np_equal(y.numpy(), np.array(((1.0, 2.0, 0.0, -1.0, 0.0, 0.0, 0.0),), dtype=float))
2612
+ assert_np_equal(x.grad.numpy(), np.array(((1.0, 1.0),), dtype=float))
2613
+
2614
+
2513
2615
  devices = get_test_devices()
2514
2616
 
2515
2617
 
@@ -2721,13 +2823,17 @@ add_function_test(
2721
2823
  )
2722
2824
  add_function_test(TestSpatial, "test_transform_extract", test_transform_extract, devices=devices)
2723
2825
  add_function_test(TestSpatial, "test_transform_assign", test_transform_assign, devices=devices)
2724
- add_function_test(TestSpatial, "test_transform_assign_copy", test_transform_assign_copy, devices=devices)
2725
2826
  add_function_test(TestSpatial, "test_transform_array_extract", test_transform_array_extract, devices=devices)
2726
2827
  add_function_test(TestSpatial, "test_transform_array_assign", test_transform_array_assign, devices=devices)
2727
2828
  add_function_test(TestSpatial, "test_transform_add_inplace", test_transform_add_inplace, devices=devices)
2728
2829
  add_function_test(TestSpatial, "test_transform_sub_inplace", test_transform_sub_inplace, devices=devices)
2729
2830
  add_function_test(TestSpatial, "test_transform_array_add_inplace", test_transform_array_add_inplace, devices=devices)
2730
2831
  add_function_test(TestSpatial, "test_transform_array_sub_inplace", test_transform_array_sub_inplace, devices=devices)
2832
+ add_function_test(TestSpatial, "test_transform_indexing_assign", test_transform_indexing_assign, devices=devices)
2833
+ add_function_test(TestSpatial, "test_transform_slicing_assign", test_transform_slicing_assign, devices=devices)
2834
+ add_function_test(
2835
+ TestSpatial, "test_transform_slicing_assign_backward", test_transform_slicing_assign_backward, devices=devices
2836
+ )
2731
2837
 
2732
2838
 
2733
2839
  if __name__ == "__main__":
@@ -0,0 +1,160 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ import unittest
17
+
18
+ import numpy as np
19
+
20
+ import warp as wp
21
+ from warp.tests.unittest_utils import *
22
+
23
+
24
+ def setUpModule():
25
+ wp.config.enable_vector_component_overwrites = True
26
+
27
+
28
+ def tearDownModule():
29
+ wp.config.enable_vector_component_overwrites = False
30
+
31
+
32
+ @wp.kernel
33
+ def transform_assign_subscript(x: wp.array(dtype=float), y: wp.array(dtype=wp.transform)):
34
+ i = wp.tid()
35
+
36
+ a = wp.transform()
37
+ a[0] = 1.0 * x[i]
38
+ a[1] = 2.0 * x[i]
39
+ a[2] = 3.0 * x[i]
40
+ a[3] = 4.0 * x[i]
41
+ a[4] = 5.0 * x[i]
42
+ a[5] = 6.0 * x[i]
43
+ a[6] = 7.0 * x[i]
44
+ y[i] = a
45
+
46
+
47
+ @wp.kernel
48
+ def transform_assign_attribute(x: wp.array(dtype=wp.vec3), y: wp.array(dtype=wp.quat), z: wp.array(dtype=wp.transform)):
49
+ i = wp.tid()
50
+
51
+ a = wp.transform()
52
+ a.p = x[i]
53
+ a.q = y[i]
54
+ z[i] = a
55
+
56
+
57
+ def test_transform_assign(test, device):
58
+ x = wp.ones(1, dtype=float, requires_grad=True, device=device)
59
+ y = wp.zeros(1, dtype=wp.transform, requires_grad=True, device=device)
60
+
61
+ tape = wp.Tape()
62
+ with tape:
63
+ wp.launch(transform_assign_subscript, 1, inputs=[x], outputs=[y], device=device)
64
+
65
+ y.grad = wp.ones_like(y)
66
+ tape.backward()
67
+
68
+ assert_np_equal(y.numpy(), np.array([[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]], dtype=float))
69
+ assert_np_equal(x.grad.numpy(), np.array([28.0], dtype=float))
70
+
71
+ x = wp.ones(1, dtype=wp.vec3, requires_grad=True, device=device)
72
+ y = wp.ones(1, dtype=wp.quat, requires_grad=True, device=device)
73
+ z = wp.zeros(1, dtype=wp.transform, requires_grad=True, device=device)
74
+
75
+ tape = wp.Tape()
76
+ with tape:
77
+ wp.launch(transform_assign_attribute, 1, inputs=[x, y], outputs=[z], device=device)
78
+
79
+ z.grad = wp.ones_like(z)
80
+ tape.backward()
81
+
82
+ assert_np_equal(z.numpy(), np.array([[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]], dtype=float))
83
+ assert_np_equal(x.grad.numpy(), np.array([[1.0, 1.0, 1.0]], dtype=float))
84
+ assert_np_equal(y.grad.numpy(), np.array([[1.0, 1.0, 1.0, 1.0]], dtype=float))
85
+
86
+
87
+ def test_transform_assign_copy(test, device):
88
+ @wp.kernel(module="unique")
89
+ def transform_assign_overwrite(x: wp.array(dtype=wp.transform), y: wp.array(dtype=wp.transform)):
90
+ tid = wp.tid()
91
+
92
+ a = wp.transform()
93
+ b = x[tid]
94
+ a = b
95
+ a[1] = 3.0
96
+
97
+ y[tid] = a
98
+
99
+ x = wp.ones(1, dtype=wp.transform, device=device, requires_grad=True)
100
+ y = wp.zeros(1, dtype=wp.transform, device=device, requires_grad=True)
101
+
102
+ tape = wp.Tape()
103
+ with tape:
104
+ wp.launch(transform_assign_overwrite, dim=1, inputs=[x, y], device=device)
105
+
106
+ y.grad = wp.ones_like(y, requires_grad=False)
107
+ tape.backward()
108
+
109
+ assert_np_equal(y.numpy(), np.array([[1.0, 3.0, 1.0, 1.0, 1.0, 1.0, 1.0]], dtype=float))
110
+ assert_np_equal(x.grad.numpy(), np.array([[1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0]], dtype=float))
111
+
112
+
113
+ def test_transform_slicing_assign_backward(test, device):
114
+ @wp.kernel(module="unique")
115
+ def kernel(arr_x: wp.array(dtype=wp.vec2), arr_y: wp.array(dtype=wp.transform)):
116
+ i = wp.tid()
117
+
118
+ x = arr_x[i]
119
+ y = arr_y[i]
120
+
121
+ y[:2] = x
122
+ y[1:-4] += x[:2]
123
+ y[3:1:-1] -= x[0:]
124
+
125
+ arr_y[i] = y
126
+
127
+ x = wp.ones(1, dtype=wp.vec2, requires_grad=True, device=device)
128
+ y = wp.zeros(1, dtype=wp.transform, requires_grad=True, device=device)
129
+
130
+ tape = wp.Tape()
131
+ with tape:
132
+ wp.launch(kernel, 1, inputs=(x,), outputs=(y,), device=device)
133
+
134
+ y.grad = wp.ones_like(y)
135
+ tape.backward()
136
+
137
+ assert_np_equal(y.numpy(), np.array(((1.0, 2.0, 0.0, -1.0, 0.0, 0.0, 0.0),), dtype=float))
138
+ assert_np_equal(x.grad.numpy(), np.array(((1.0, 1.0),), dtype=float))
139
+
140
+
141
+ devices = get_test_devices()
142
+
143
+
144
+ class TestSpatialAssignCopy(unittest.TestCase):
145
+ pass
146
+
147
+
148
+ add_function_test(TestSpatialAssignCopy, "test_transform_assign", test_transform_assign, devices=devices)
149
+ add_function_test(TestSpatialAssignCopy, "test_transform_assign_copy", test_transform_assign_copy, devices=devices)
150
+ add_function_test(
151
+ TestSpatialAssignCopy,
152
+ "test_transform_slicing_assign_backward",
153
+ test_transform_slicing_assign_backward,
154
+ devices=devices,
155
+ )
156
+
157
+
158
+ if __name__ == "__main__":
159
+ wp.clear_kernel_cache()
160
+ unittest.main(verbosity=2)
warp/tests/test_struct.py CHANGED
@@ -235,6 +235,44 @@ def test_nested_struct(test, device):
235
235
  )
236
236
 
237
237
 
238
+ @wp.struct
239
+ class MatStruct:
240
+ m: wp.mat44
241
+
242
+
243
+ @wp.kernel
244
+ def kernel_nested_mat(out: wp.array(dtype=wp.mat44)):
245
+ s = MatStruct()
246
+ m = wp.mat44()
247
+
248
+ s.m[1, 2] = 3.0
249
+
250
+ out[0] = s.m
251
+
252
+
253
+ def test_nested_mat(test, device):
254
+ m = wp.array([wp.mat44()], dtype=wp.mat44, device=device)
255
+ wp.launch(kernel_nested_mat, dim=1, outputs=[m], device=device)
256
+ wp.synchronize()
257
+
258
+ out = m.numpy()
259
+ assert_np_equal(out[0][1, 2], 3.0)
260
+
261
+
262
+ def test_assign_view(test, device):
263
+ @wp.kernel
264
+ def kernel_assign_view(out: wp.array2d(dtype=wp.mat44)):
265
+ out[0][2, 2] = 6.0
266
+
267
+ m = wp.array([[wp.mat44()]], dtype=wp.mat44, device=device)
268
+
269
+ with test.assertRaisesRegex(
270
+ wp.codegen.WarpCodegenError,
271
+ r"Incorrect number of indices specified for array indexing",
272
+ ):
273
+ wp.launch(kernel_assign_view, dim=[1, 1], outputs=[m], device=device)
274
+
275
+
238
276
  def test_struct_attribute_error(test, device):
239
277
  @wp.kernel
240
278
  def kernel(foo: Foo):
@@ -751,9 +789,6 @@ def test_struct_array_gc_requires_grad_toggle(test, device):
751
789
  tape.backward(loss=loss_wp)
752
790
 
753
791
 
754
- devices = get_test_devices()
755
-
756
-
757
792
  class TestStruct(unittest.TestCase):
758
793
  # check structs default initialized in Python correctly
759
794
  def test_struct_default_attributes_python(self):
@@ -772,6 +807,9 @@ class TestStruct(unittest.TestCase):
772
807
  np.testing.assert_equal(arr.numpy().tolist(), expected)
773
808
 
774
809
 
810
+ devices = get_test_devices()
811
+
812
+
775
813
  add_function_test(TestStruct, "test_step", test_step, devices=devices)
776
814
  add_function_test(TestStruct, "test_step_grad", test_step_grad, devices=devices)
777
815
  add_kernel_test(TestStruct, kernel=test_empty, name="test_empty", dim=1, inputs=[Empty()], devices=devices)
@@ -785,6 +823,8 @@ add_kernel_test(
785
823
  )
786
824
  add_kernel_test(TestStruct, kernel=test_return, name="test_return", dim=1, inputs=[], devices=devices)
787
825
  add_function_test(TestStruct, "test_nested_struct", test_nested_struct, devices=devices)
826
+ add_function_test(TestStruct, "test_nested_mat", test_nested_mat, devices=devices)
827
+ add_function_test(TestStruct, "test_assign_view", test_assign_view, devices=devices)
788
828
  add_function_test(TestStruct, "test_struct_attribute_error", test_struct_attribute_error, devices=devices)
789
829
  add_function_test(TestStruct, "test_struct_inheritance_error", test_struct_inheritance_error, devices=devices)
790
830
  add_function_test(TestStruct, "test_nested_array_struct", test_nested_array_struct, devices=devices)