Spaces:
Sleeping
Sleeping
| # Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. | |
| # NVIDIA CORPORATION and its licensors retain all intellectual property | |
| # and proprietary rights in and to this software, related documentation | |
| # and any modifications thereto. Any use, reproduction, disclosure or | |
| # distribution of this software and related documentation without an express | |
| # license agreement from NVIDIA CORPORATION is strictly prohibited. | |
| import math | |
| import unittest | |
| import numpy as np | |
| import warp as wp | |
| from warp.tests.unittest_utils import * | |
| wp.init() | |
| def sqr(x: float): | |
| return x * x | |
| # test nested user function calls | |
| # and explicit return type hints | |
| def cube(x: float) -> float: | |
| return sqr(x) * x | |
| def custom(x: int): | |
| return x + 1 | |
| def custom(x: float): | |
| return x + 1.0 | |
| def custom(x: wp.vec3): | |
| return x + wp.vec3(1.0, 0.0, 0.0) | |
| def noreturn(x: wp.vec3): | |
| x = x + wp.vec3(0.0, 1.0, 0.0) | |
| wp.expect_eq(x, wp.vec3(1.0, 1.0, 0.0)) | |
| def test_overload_func(): | |
| # tests overloading a custom @wp.func | |
| i = custom(1) | |
| f = custom(1.0) | |
| v = custom(wp.vec3(1.0, 0.0, 0.0)) | |
| wp.expect_eq(i, 2) | |
| wp.expect_eq(f, 2.0) | |
| wp.expect_eq(v, wp.vec3(2.0, 0.0, 0.0)) | |
| noreturn(wp.vec3(1.0, 0.0, 0.0)) | |
| def foo(x: int): | |
| # This shouldn't be picked up. | |
| return x * 2 | |
| def foo(x: int): | |
| return x * 3 | |
| def test_override_func(): | |
| i = foo(1) | |
| wp.expect_eq(i, 3) | |
| def test_func_closure_capture(test, device): | |
| def make_closure_kernel(func): | |
| def closure_kernel_fn(data: wp.array(dtype=float), expected: float): | |
| f = func(data[wp.tid()]) | |
| wp.expect_eq(f, expected) | |
| return wp.Kernel(func=closure_kernel_fn) | |
| sqr_closure = make_closure_kernel(sqr) | |
| cube_closure = make_closure_kernel(cube) | |
| data = wp.array([2.0], dtype=float, device=device) | |
| expected_sqr = 4.0 | |
| expected_cube = 8.0 | |
| wp.launch(sqr_closure, dim=data.shape, inputs=[data, expected_sqr], device=device) | |
| wp.launch(cube_closure, dim=data.shape, inputs=[data, expected_cube], device=device) | |
| def test_func(param1: wp.int32, param2: wp.int32, param3: wp.int32) -> wp.float32: | |
| return 1.0 | |
| def test_return_kernel(test_data: wp.array(dtype=wp.float32)): | |
| tid = wp.tid() | |
| test_data[tid] = wp.lerp(test_func(0, 1, 2), test_func(0, 1, 2), 0.5) | |
| def test_return_func(test, device): | |
| test_data = wp.zeros(100, dtype=wp.float32, device=device) | |
| wp.launch(kernel=test_return_kernel, dim=test_data.size, inputs=[test_data], device=device) | |
| def multi_valued_func(a: wp.float32, b: wp.float32): | |
| return a + b, a - b, a * b, a / b | |
| def test_multi_valued_func(test, device): | |
| def test_multi_valued_kernel(test_data1: wp.array(dtype=wp.float32), test_data2: wp.array(dtype=wp.float32)): | |
| tid = wp.tid() | |
| d1, d2 = test_data1[tid], test_data2[tid] | |
| a, b, c, d = multi_valued_func(d1, d2) | |
| wp.expect_eq(a, d1 + d2) | |
| wp.expect_eq(b, d1 - d2) | |
| wp.expect_eq(c, d1 * d2) | |
| wp.expect_eq(d, d1 / d2) | |
| test_data1 = wp.array(np.arange(100), dtype=wp.float32, device=device) | |
| test_data2 = wp.array(np.arange(100, 0, -1), dtype=wp.float32, device=device) | |
| wp.launch(kernel=test_multi_valued_kernel, dim=test_data1.size, inputs=[test_data1, test_data2], device=device) | |
| def test_func_defaults(): | |
| # test default as expected | |
| wp.expect_near(1.0, 1.0 + 1.0e-6) | |
| # test that changing tolerance still works | |
| wp.expect_near(1.0, 1.1, 0.5) | |
| def sign(x: float): | |
| return 123.0 | |
| def test_builtin_shadowing(): | |
| wp.expect_eq(sign(1.23), 123.0) | |
| devices = get_test_devices() | |
| class TestFunc(unittest.TestCase): | |
| def test_user_func_export(self): | |
| # tests calling overloaded user-defined functions from Python | |
| i = custom(1) | |
| f = custom(1.0) | |
| v = custom(wp.vec3(1.0, 0.0, 0.0)) | |
| self.assertEqual(i, 2) | |
| self.assertEqual(f, 2.0) | |
| assert_np_equal(np.array([*v]), np.array([2.0, 0.0, 0.0])) | |
| def test_native_func_export(self): | |
| # tests calling native functions from Python | |
| q = wp.quat(0.0, 0.0, 0.0, 1.0) | |
| assert_np_equal(np.array([*q]), np.array([0.0, 0.0, 0.0, 1.0])) | |
| r = wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), 2.0) | |
| assert_np_equal(np.array([*r]), np.array([0.8414709568023682, 0.0, 0.0, 0.5403022170066833]), tol=1.0e-3) | |
| q = wp.quat(1.0, 2.0, 3.0, 4.0) | |
| q = wp.normalize(q) * 2.0 | |
| assert_np_equal( | |
| np.array([*q]), | |
| np.array([0.18257418274879456, 0.3651483654975891, 0.547722578048706, 0.7302967309951782]) * 2.0, | |
| tol=1.0e-3, | |
| ) | |
| v2 = wp.vec2(1.0, 2.0) | |
| v2 = wp.normalize(v2) * 2.0 | |
| assert_np_equal(np.array([*v2]), np.array([0.4472135901451111, 0.8944271802902222]) * 2.0, tol=1.0e-3) | |
| v3 = wp.vec3(1.0, 2.0, 3.0) | |
| v3 = wp.normalize(v3) * 2.0 | |
| assert_np_equal( | |
| np.array([*v3]), np.array([0.26726123690605164, 0.5345224738121033, 0.8017836809158325]) * 2.0, tol=1.0e-3 | |
| ) | |
| v4 = wp.vec4(1.0, 2.0, 3.0, 4.0) | |
| v4 = wp.normalize(v4) * 2.0 | |
| assert_np_equal( | |
| np.array([*v4]), | |
| np.array([0.18257418274879456, 0.3651483654975891, 0.547722578048706, 0.7302967309951782]) * 2.0, | |
| tol=1.0e-3, | |
| ) | |
| v = wp.vec2(0.0) | |
| v += wp.vec2(1.0, 1.0) | |
| assert v == wp.vec2(1.0, 1.0) | |
| v -= wp.vec2(1.0, 1.0) | |
| assert v == wp.vec2(0.0, 0.0) | |
| v = wp.vec2(2.0, 2.0) - wp.vec2(1.0, 1.0) | |
| assert v == wp.vec2(1.0, 1.0) | |
| v *= 2.0 | |
| assert v == wp.vec2(2.0, 2.0) | |
| v = v * 2.0 | |
| assert v == wp.vec2(4.0, 4.0) | |
| v = v / 2.0 | |
| assert v == wp.vec2(2.0, 2.0) | |
| v /= 2.0 | |
| assert v == wp.vec2(1.0, 1.0) | |
| v = -v | |
| assert v == wp.vec2(-1.0, -1.0) | |
| v = +v | |
| assert v == wp.vec2(-1.0, -1.0) | |
| m22 = wp.mat22(1.0, 2.0, 3.0, 4.0) | |
| m22 = m22 + m22 | |
| self.assertEqual(m22[1, 1], 8.0) | |
| self.assertEqual(str(m22), "[[2.0, 4.0],\n [6.0, 8.0]]") | |
| t = wp.transform( | |
| wp.vec3(1.0, 2.0, 3.0), | |
| wp.quat(4.0, 5.0, 6.0, 7.0), | |
| ) | |
| self.assertSequenceEqual(t, (1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0)) | |
| self.assertSequenceEqual(t * wp.transform(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0), (396.0, 432.0, 720.0, 56.0, 70.0, 84.0, -28.0)) | |
| self.assertSequenceEqual( | |
| t * wp.transform((1.0, 2.0, 3.0), (4.0, 5.0, 6.0, 7.0)), (396.0, 432.0, 720.0, 56.0, 70.0, 84.0, -28.0) | |
| ) | |
| t = wp.transform() | |
| self.assertSequenceEqual(t, (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0)) | |
| t = wp.transform(p=(1.0, 2.0, 3.0), q=(4.0, 5.0, 6.0, 7.0)) | |
| self.assertSequenceEqual(t, (1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0)) | |
| t = wp.transform(q=(4.0, 5.0, 6.0, 7.0), p=(1.0, 2.0, 3.0)) | |
| self.assertSequenceEqual(t, (1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0)) | |
| t = wp.transform((1.0, 2.0, 3.0), q=(4.0, 5.0, 6.0, 7.0)) | |
| self.assertSequenceEqual(t, (1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0)) | |
| t = wp.transform(p=(1.0, 2.0, 3.0)) | |
| self.assertSequenceEqual(t, (1.0, 2.0, 3.0, 0.0, 0.0, 0.0, 1.0)) | |
| t = wp.transform(q=(4.0, 5.0, 6.0, 7.0)) | |
| self.assertSequenceEqual(t, (0.0, 0.0, 0.0, 4.0, 5.0, 6.0, 7.0)) | |
| t = wp.transform((1.0, 2.0, 3.0), (4.0, 5.0, 6.0, 7.0)) | |
| self.assertSequenceEqual(t, (1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0)) | |
| t = wp.transform(p=wp.vec3(1.0, 2.0, 3.0), q=wp.quat(4.0, 5.0, 6.0, 7.0)) | |
| self.assertSequenceEqual(t, (1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0)) | |
| t = wp.transform(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0) | |
| self.assertSequenceEqual(t, (1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0)) | |
| t = wp.transform(wp.transform(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0)) | |
| self.assertSequenceEqual(t, (1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0)) | |
| t = wp.transform(*wp.transform(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0)) | |
| self.assertSequenceEqual(t, (1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0)) | |
| transformf = wp.types.transformation(dtype=float) | |
| t = wp.transformf((1.0, 2.0, 3.0), (4.0, 5.0, 6.0, 7.0)) | |
| self.assertSequenceEqual( | |
| t + transformf((2.0, 3.0, 4.0), (5.0, 6.0, 7.0, 8.0)), | |
| (3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0), | |
| ) | |
| self.assertSequenceEqual( | |
| t - transformf((2.0, 3.0, 4.0), (5.0, 6.0, 7.0, 8.0)), | |
| (-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0), | |
| ) | |
| f = wp.sin(math.pi * 0.5) | |
| self.assertAlmostEqual(f, 1.0, places=3) | |
| m = wp.mat22(0.0, 0.0, 0.0, 0.0) | |
| m += wp.mat22(1.0, 1.0, 1.0, 1.0) | |
| assert m == wp.mat22(1.0, 1.0, 1.0, 1.0) | |
| m -= wp.mat22(1.0, 1.0, 1.0, 1.0) | |
| assert m == wp.mat22(0.0, 0.0, 0.0, 0.0) | |
| m = wp.mat22(2.0, 2.0, 2.0, 2.0) - wp.mat22(1.0, 1.0, 1.0, 1.0) | |
| assert m == wp.mat22(1.0, 1.0, 1.0, 1.0) | |
| m *= 2.0 | |
| assert m == wp.mat22(2.0, 2.0, 2.0, 2.0) | |
| m = m * 2.0 | |
| assert m == wp.mat22(4.0, 4.0, 4.0, 4.0) | |
| m = m / 2.0 | |
| assert m == wp.mat22(2.0, 2.0, 2.0, 2.0) | |
| m /= 2.0 | |
| assert m == wp.mat22(1.0, 1.0, 1.0, 1.0) | |
| m = -m | |
| assert m == wp.mat22(-1.0, -1.0, -1.0, -1.0) | |
| m = +m | |
| assert m == wp.mat22(-1.0, -1.0, -1.0, -1.0) | |
| m = m * m | |
| assert m == wp.mat22(2.0, 2.0, 2.0, 2.0) | |
| def test_native_function_error_resolution(self): | |
| a = wp.mat22f(1.0, 2.0, 3.0, 4.0) | |
| b = wp.mat22d(1.0, 2.0, 3.0, 4.0) | |
| with self.assertRaisesRegex( | |
| RuntimeError, | |
| r"^Couldn't find a function 'mul' compatible with " r"the arguments 'mat22f, mat22d'$", | |
| ): | |
| a * b | |
| add_kernel_test(TestFunc, kernel=test_overload_func, name="test_overload_func", dim=1, devices=devices) | |
| add_function_test(TestFunc, func=test_return_func, name="test_return_func", devices=devices) | |
| add_kernel_test(TestFunc, kernel=test_override_func, name="test_override_func", dim=1, devices=devices) | |
| add_function_test(TestFunc, func=test_func_closure_capture, name="test_func_closure_capture", devices=devices) | |
| add_function_test(TestFunc, func=test_multi_valued_func, name="test_multi_valued_func", devices=devices) | |
| add_kernel_test(TestFunc, kernel=test_func_defaults, name="test_func_defaults", dim=1, devices=devices) | |
| add_kernel_test(TestFunc, kernel=test_builtin_shadowing, name="test_builtin_shadowing", dim=1, devices=devices) | |
| if __name__ == "__main__": | |
| wp.build.clear_kernel_cache() | |
| unittest.main(verbosity=2) | |