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 builtins | |
| from typing import Any, Callable, Tuple | |
| from warp.codegen import Reference | |
| from warp.types import * | |
| from .context import add_builtin | |
| def sametype_value_func(default): | |
| def fn(arg_types, kwds, _): | |
| if arg_types is None: | |
| return default | |
| if not all(types_equal(arg_types[0], t) for t in arg_types[1:]): | |
| raise RuntimeError(f"Input types must be the same, found: {[type_repr(t) for t in arg_types]}") | |
| return arg_types[0] | |
| return fn | |
| # --------------------------------- | |
| # Scalar Math | |
| add_builtin( | |
| "min", | |
| input_types={"x": Scalar, "y": Scalar}, | |
| value_func=sametype_value_func(Scalar), | |
| doc="Return the minimum of two scalars.", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "max", | |
| input_types={"x": Scalar, "y": Scalar}, | |
| value_func=sametype_value_func(Scalar), | |
| doc="Return the maximum of two scalars.", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "clamp", | |
| input_types={"x": Scalar, "a": Scalar, "b": Scalar}, | |
| value_func=sametype_value_func(Scalar), | |
| doc="Clamp the value of ``x`` to the range [a, b].", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "abs", | |
| input_types={"x": Scalar}, | |
| value_func=sametype_value_func(Scalar), | |
| doc="Return the absolute value of ``x``.", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "sign", | |
| input_types={"x": Scalar}, | |
| value_func=sametype_value_func(Scalar), | |
| doc="Return -1 if ``x`` < 0, return 1 otherwise.", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "step", | |
| input_types={"x": Scalar}, | |
| value_func=sametype_value_func(Scalar), | |
| doc="Return 1.0 if ``x`` < 0.0, return 0.0 otherwise.", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "nonzero", | |
| input_types={"x": Scalar}, | |
| value_func=sametype_value_func(Scalar), | |
| doc="Return 1.0 if ``x`` is not equal to zero, return 0.0 otherwise.", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "sin", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="Return the sine of ``x`` in radians.", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "cos", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="Return the cosine of ``x`` in radians.", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "acos", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="Return arccos of ``x`` in radians. Inputs are automatically clamped to [-1.0, 1.0].", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "asin", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="Return arcsin of ``x`` in radians. Inputs are automatically clamped to [-1.0, 1.0].", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "sqrt", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="Return the square root of ``x``, where ``x`` is positive.", | |
| group="Scalar Math", | |
| require_original_output_arg=True, | |
| ) | |
| add_builtin( | |
| "cbrt", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="Return the cube root of ``x``.", | |
| group="Scalar Math", | |
| require_original_output_arg=True, | |
| ) | |
| add_builtin( | |
| "tan", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="Return the tangent of ``x`` in radians.", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "atan", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="Return the arctangent of ``x`` in radians.", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "atan2", | |
| input_types={"y": Float, "x": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="Return the 2-argument arctangent, atan2, of the point ``(x, y)`` in radians.", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "sinh", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="Return the sinh of ``x``.", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "cosh", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="Return the cosh of ``x``.", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "tanh", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="Return the tanh of ``x``.", | |
| group="Scalar Math", | |
| require_original_output_arg=True, | |
| ) | |
| add_builtin( | |
| "degrees", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="Convert ``x`` from radians into degrees.", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "radians", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="Convert ``x`` from degrees into radians.", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "log", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="Return the natural logarithm (base-e) of ``x``, where ``x`` is positive.", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "log2", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="Return the binary logarithm (base-2) of ``x``, where ``x`` is positive.", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "log10", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="Return the common logarithm (base-10) of ``x``, where ``x`` is positive.", | |
| group="Scalar Math", | |
| ) | |
| add_builtin( | |
| "exp", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="Return the value of the exponential function :math:`e^x`.", | |
| group="Scalar Math", | |
| require_original_output_arg=True, | |
| ) | |
| add_builtin( | |
| "pow", | |
| input_types={"x": Float, "y": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="Return the result of ``x`` raised to power of ``y``.", | |
| group="Scalar Math", | |
| require_original_output_arg=True, | |
| ) | |
| add_builtin( | |
| "round", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| group="Scalar Math", | |
| doc="""Return the nearest integer value to ``x``, rounding halfway cases away from zero. | |
| This is the most intuitive form of rounding in the colloquial sense, but can be slower than other options like :func:`warp.rint()`. | |
| Differs from :func:`numpy.round()`, which behaves the same way as :func:`numpy.rint()`.""", | |
| ) | |
| add_builtin( | |
| "rint", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| group="Scalar Math", | |
| doc="""Return the nearest integer value to ``x``, rounding halfway cases to nearest even integer. | |
| It is generally faster than :func:`warp.round()`. Equivalent to :func:`numpy.rint()`.""", | |
| ) | |
| add_builtin( | |
| "trunc", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| group="Scalar Math", | |
| doc="""Return the nearest integer that is closer to zero than ``x``. | |
| In other words, it discards the fractional part of ``x``. | |
| It is similar to casting ``float(int(x))``, but preserves the negative sign when x is in the range [-0.0, -1.0). | |
| Equivalent to :func:`numpy.trunc()` and :func:`numpy.fix()`.""", | |
| ) | |
| add_builtin( | |
| "floor", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| group="Scalar Math", | |
| doc="""Return the largest integer that is less than or equal to ``x``.""", | |
| ) | |
| add_builtin( | |
| "ceil", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| group="Scalar Math", | |
| doc="""Return the smallest integer that is greater than or equal to ``x``.""", | |
| ) | |
| add_builtin( | |
| "frac", | |
| input_types={"x": Float}, | |
| value_func=sametype_value_func(Float), | |
| group="Scalar Math", | |
| doc="""Retrieve the fractional part of x. | |
| In other words, it discards the integer part of x and is equivalent to ``x - trunc(x)``.""", | |
| ) | |
| def infer_scalar_type(arg_types): | |
| if arg_types is None: | |
| return Scalar | |
| def iterate_scalar_types(arg_types): | |
| for t in arg_types: | |
| if hasattr(t, "_wp_scalar_type_"): | |
| yield t._wp_scalar_type_ | |
| elif t in scalar_types: | |
| yield t | |
| scalarTypes = set(iterate_scalar_types(arg_types)) | |
| if len(scalarTypes) > 1: | |
| raise RuntimeError( | |
| f"Couldn't figure out return type as arguments have multiple precisions: {list(scalarTypes)}" | |
| ) | |
| return list(scalarTypes)[0] | |
| def sametype_scalar_value_func(arg_types, kwds, _): | |
| if arg_types is None: | |
| return Scalar | |
| if not all(types_equal(arg_types[0], t) for t in arg_types[1:]): | |
| raise RuntimeError(f"Input types must be exactly the same, {[t for t in arg_types]}") | |
| return infer_scalar_type(arg_types) | |
| # --------------------------------- | |
| # Vector Math | |
| add_builtin( | |
| "dot", | |
| input_types={"x": vector(length=Any, dtype=Scalar), "y": vector(length=Any, dtype=Scalar)}, | |
| value_func=sametype_scalar_value_func, | |
| group="Vector Math", | |
| doc="Compute the dot product between two vectors.", | |
| ) | |
| add_builtin( | |
| "ddot", | |
| input_types={"x": matrix(shape=(Any, Any), dtype=Scalar), "y": matrix(shape=(Any, Any), dtype=Scalar)}, | |
| value_func=sametype_scalar_value_func, | |
| group="Vector Math", | |
| doc="Compute the double dot product between two matrices.", | |
| ) | |
| add_builtin( | |
| "min", | |
| input_types={"x": vector(length=Any, dtype=Scalar), "y": vector(length=Any, dtype=Scalar)}, | |
| value_func=sametype_value_func(vector(length=Any, dtype=Scalar)), | |
| doc="Return the element-wise minimum of two vectors.", | |
| group="Vector Math", | |
| ) | |
| add_builtin( | |
| "max", | |
| input_types={"x": vector(length=Any, dtype=Scalar), "y": vector(length=Any, dtype=Scalar)}, | |
| value_func=sametype_value_func(vector(length=Any, dtype=Scalar)), | |
| doc="Return the element-wise maximum of two vectors.", | |
| group="Vector Math", | |
| ) | |
| add_builtin( | |
| "min", | |
| input_types={"v": vector(length=Any, dtype=Scalar)}, | |
| value_func=sametype_scalar_value_func, | |
| doc="Return the minimum element of a vector ``v``.", | |
| group="Vector Math", | |
| ) | |
| add_builtin( | |
| "max", | |
| input_types={"v": vector(length=Any, dtype=Scalar)}, | |
| value_func=sametype_scalar_value_func, | |
| doc="Return the maximum element of a vector ``v``.", | |
| group="Vector Math", | |
| ) | |
| add_builtin( | |
| "argmin", | |
| input_types={"v": vector(length=Any, dtype=Scalar)}, | |
| value_func=lambda arg_types, kwds, _: warp.uint32, | |
| doc="Return the index of the minimum element of a vector ``v``.", | |
| group="Vector Math", | |
| missing_grad=True, | |
| ) | |
| add_builtin( | |
| "argmax", | |
| input_types={"v": vector(length=Any, dtype=Scalar)}, | |
| value_func=lambda arg_types, kwds, _: warp.uint32, | |
| doc="Return the index of the maximum element of a vector ``v``.", | |
| group="Vector Math", | |
| missing_grad=True, | |
| ) | |
| def value_func_outer(arg_types, kwds, _): | |
| if arg_types is None: | |
| return matrix(shape=(Any, Any), dtype=Scalar) | |
| scalarType = infer_scalar_type(arg_types) | |
| vectorLengths = [t._length_ for t in arg_types] | |
| return matrix(shape=(vectorLengths), dtype=scalarType) | |
| add_builtin( | |
| "outer", | |
| input_types={"x": vector(length=Any, dtype=Scalar), "y": vector(length=Any, dtype=Scalar)}, | |
| value_func=value_func_outer, | |
| group="Vector Math", | |
| doc="Compute the outer product ``x*y^T`` for two vectors.", | |
| ) | |
| add_builtin( | |
| "cross", | |
| input_types={"x": vector(length=3, dtype=Scalar), "y": vector(length=3, dtype=Scalar)}, | |
| value_func=sametype_value_func(vector(length=3, dtype=Scalar)), | |
| group="Vector Math", | |
| doc="Compute the cross product of two 3D vectors.", | |
| ) | |
| add_builtin( | |
| "skew", | |
| input_types={"x": vector(length=3, dtype=Scalar)}, | |
| value_func=lambda arg_types, kwds, _: matrix(shape=(3, 3), dtype=arg_types[0]._wp_scalar_type_), | |
| group="Vector Math", | |
| doc="Compute the skew-symmetric 3x3 matrix for a 3D vector ``x``.", | |
| ) | |
| add_builtin( | |
| "length", | |
| input_types={"x": vector(length=Any, dtype=Float)}, | |
| value_func=sametype_scalar_value_func, | |
| group="Vector Math", | |
| doc="Compute the length of a vector ``x``.", | |
| require_original_output_arg=True, | |
| ) | |
| add_builtin( | |
| "length", | |
| input_types={"x": quaternion(dtype=Float)}, | |
| value_func=sametype_scalar_value_func, | |
| group="Vector Math", | |
| doc="Compute the length of a quaternion ``x``.", | |
| require_original_output_arg=True, | |
| ) | |
| add_builtin( | |
| "length_sq", | |
| input_types={"x": vector(length=Any, dtype=Scalar)}, | |
| value_func=sametype_scalar_value_func, | |
| group="Vector Math", | |
| doc="Compute the squared length of a 2D vector ``x``.", | |
| ) | |
| add_builtin( | |
| "length_sq", | |
| input_types={"x": quaternion(dtype=Scalar)}, | |
| value_func=sametype_scalar_value_func, | |
| group="Vector Math", | |
| doc="Compute the squared length of a quaternion ``x``.", | |
| ) | |
| add_builtin( | |
| "normalize", | |
| input_types={"x": vector(length=Any, dtype=Float)}, | |
| value_func=sametype_value_func(vector(length=Any, dtype=Scalar)), | |
| group="Vector Math", | |
| doc="Compute the normalized value of ``x``. If ``length(x)`` is 0 then the zero vector is returned.", | |
| require_original_output_arg=True, | |
| ) | |
| add_builtin( | |
| "normalize", | |
| input_types={"x": quaternion(dtype=Float)}, | |
| value_func=sametype_value_func(quaternion(dtype=Scalar)), | |
| group="Vector Math", | |
| doc="Compute the normalized value of ``x``. If ``length(x)`` is 0, then the zero quaternion is returned.", | |
| ) | |
| add_builtin( | |
| "transpose", | |
| input_types={"m": matrix(shape=(Any, Any), dtype=Scalar)}, | |
| value_func=lambda arg_types, kwds, _: matrix( | |
| shape=(arg_types[0]._shape_[1], arg_types[0]._shape_[0]), dtype=arg_types[0]._wp_scalar_type_ | |
| ), | |
| group="Vector Math", | |
| doc="Return the transpose of the matrix ``m``.", | |
| ) | |
| def value_func_mat_inv(arg_types, kwds, _): | |
| if arg_types is None: | |
| return matrix(shape=(Any, Any), dtype=Float) | |
| return arg_types[0] | |
| add_builtin( | |
| "inverse", | |
| input_types={"m": matrix(shape=(2, 2), dtype=Float)}, | |
| value_func=value_func_mat_inv, | |
| group="Vector Math", | |
| doc="Return the inverse of a 2x2 matrix ``m``.", | |
| require_original_output_arg=True, | |
| ) | |
| add_builtin( | |
| "inverse", | |
| input_types={"m": matrix(shape=(3, 3), dtype=Float)}, | |
| value_func=value_func_mat_inv, | |
| group="Vector Math", | |
| doc="Return the inverse of a 3x3 matrix ``m``.", | |
| require_original_output_arg=True, | |
| ) | |
| add_builtin( | |
| "inverse", | |
| input_types={"m": matrix(shape=(4, 4), dtype=Float)}, | |
| value_func=value_func_mat_inv, | |
| group="Vector Math", | |
| doc="Return the inverse of a 4x4 matrix ``m``.", | |
| require_original_output_arg=True, | |
| ) | |
| def value_func_mat_det(arg_types, kwds, _): | |
| if arg_types is None: | |
| return Scalar | |
| return arg_types[0]._wp_scalar_type_ | |
| add_builtin( | |
| "determinant", | |
| input_types={"m": matrix(shape=(2, 2), dtype=Float)}, | |
| value_func=value_func_mat_det, | |
| group="Vector Math", | |
| doc="Return the determinant of a 2x2 matrix ``m``.", | |
| ) | |
| add_builtin( | |
| "determinant", | |
| input_types={"m": matrix(shape=(3, 3), dtype=Float)}, | |
| value_func=value_func_mat_det, | |
| group="Vector Math", | |
| doc="Return the determinant of a 3x3 matrix ``m``.", | |
| ) | |
| add_builtin( | |
| "determinant", | |
| input_types={"m": matrix(shape=(4, 4), dtype=Float)}, | |
| value_func=value_func_mat_det, | |
| group="Vector Math", | |
| doc="Return the determinant of a 4x4 matrix ``m``.", | |
| ) | |
| def value_func_mat_trace(arg_types, kwds, _): | |
| if arg_types is None: | |
| return Scalar | |
| if arg_types[0]._shape_[0] != arg_types[0]._shape_[1]: | |
| raise RuntimeError(f"Matrix shape is {arg_types[0]._shape_}. Cannot find the trace of non square matrices") | |
| return arg_types[0]._wp_scalar_type_ | |
| add_builtin( | |
| "trace", | |
| input_types={"m": matrix(shape=(Any, Any), dtype=Scalar)}, | |
| value_func=value_func_mat_trace, | |
| group="Vector Math", | |
| doc="Return the trace of the matrix ``m``.", | |
| ) | |
| def value_func_diag(arg_types, kwds, _): | |
| if arg_types is None: | |
| return matrix(shape=(Any, Any), dtype=Scalar) | |
| else: | |
| return matrix(shape=(arg_types[0]._length_, arg_types[0]._length_), dtype=arg_types[0]._wp_scalar_type_) | |
| add_builtin( | |
| "diag", | |
| input_types={"d": vector(length=Any, dtype=Scalar)}, | |
| value_func=value_func_diag, | |
| group="Vector Math", | |
| doc="Returns a matrix with the components of the vector ``d`` on the diagonal.", | |
| ) | |
| def value_func_get_diag(arg_types, kwds, _): | |
| if arg_types is None: | |
| return vector(length=(Any), dtype=Scalar) | |
| else: | |
| if arg_types[0]._shape_[0] != arg_types[0]._shape_[1]: | |
| raise RuntimeError( | |
| f"Matrix shape is {arg_types[0]._shape_}; get_diag is only available for square matrices." | |
| ) | |
| return vector(length=arg_types[0]._shape_[0], dtype=arg_types[0]._wp_scalar_type_) | |
| add_builtin( | |
| "get_diag", | |
| input_types={"m": matrix(shape=(Any, Any), dtype=Scalar)}, | |
| value_func=value_func_get_diag, | |
| group="Vector Math", | |
| doc="Returns a vector containing the diagonal elements of the square matrix ``m``.", | |
| ) | |
| add_builtin( | |
| "cw_mul", | |
| input_types={"x": vector(length=Any, dtype=Scalar), "y": vector(length=Any, dtype=Scalar)}, | |
| value_func=sametype_value_func(vector(length=Any, dtype=Scalar)), | |
| group="Vector Math", | |
| doc="Component-wise multiplication of two 2D vectors.", | |
| ) | |
| add_builtin( | |
| "cw_div", | |
| input_types={"x": vector(length=Any, dtype=Scalar), "y": vector(length=Any, dtype=Scalar)}, | |
| value_func=sametype_value_func(vector(length=Any, dtype=Scalar)), | |
| group="Vector Math", | |
| doc="Component-wise division of two 2D vectors.", | |
| require_original_output_arg=True, | |
| ) | |
| add_builtin( | |
| "cw_mul", | |
| input_types={"x": matrix(shape=(Any, Any), dtype=Scalar), "y": matrix(shape=(Any, Any), dtype=Scalar)}, | |
| value_func=sametype_value_func(matrix(shape=(Any, Any), dtype=Scalar)), | |
| group="Vector Math", | |
| doc="Component-wise multiplication of two 2D vectors.", | |
| ) | |
| add_builtin( | |
| "cw_div", | |
| input_types={"x": matrix(shape=(Any, Any), dtype=Scalar), "y": matrix(shape=(Any, Any), dtype=Scalar)}, | |
| value_func=sametype_value_func(matrix(shape=(Any, Any), dtype=Scalar)), | |
| group="Vector Math", | |
| doc="Component-wise division of two 2D vectors.", | |
| require_original_output_arg=True, | |
| ) | |
| # scalar type constructors between all storage / compute types | |
| scalar_types_all = [*scalar_types, int, float] | |
| for t in scalar_types_all: | |
| for u in scalar_types_all: | |
| add_builtin( | |
| t.__name__, input_types={"u": u}, value_type=t, doc="", hidden=True, group="Scalar Math", export=False | |
| ) | |
| for u in [bool, builtins.bool]: | |
| add_builtin(bool.__name__, input_types={"u": u}, value_type=bool, doc="", hidden=True, export=False, namespace="") | |
| def vector_constructor_func(arg_types, kwds, templates): | |
| if arg_types is None: | |
| return vector(length=Any, dtype=Scalar) | |
| if templates is None or len(templates) == 0: | |
| # handle construction of anonymous (undeclared) vector types | |
| if "length" in kwds: | |
| if len(arg_types) == 0: | |
| if "dtype" not in kwds: | |
| raise RuntimeError( | |
| "vec() must have dtype as a keyword argument if it has no positional arguments, e.g.: wp.vector(length=5, dtype=wp.float32)" | |
| ) | |
| # zero initialization e.g.: wp.vector(length=5, dtype=wp.float32) | |
| veclen = kwds["length"] | |
| vectype = kwds["dtype"] | |
| elif len(arg_types) == 1: | |
| # value initialization e.g.: wp.vec(1.0, length=5) | |
| veclen = kwds["length"] | |
| vectype = arg_types[0] | |
| if getattr(vectype, "_wp_generic_type_str_", None) == "vec_t": | |
| # constructor from another vector | |
| if vectype._length_ != veclen: | |
| raise RuntimeError( | |
| f"Incompatible vector lengths for casting copy constructor, {veclen} vs {vectype._length_}" | |
| ) | |
| vectype = vectype._wp_scalar_type_ | |
| else: | |
| raise RuntimeError( | |
| "vec() must have one scalar argument or the dtype keyword argument if the length keyword argument is specified, e.g.: wp.vec(1.0, length=5)" | |
| ) | |
| else: | |
| if len(arg_types) == 0: | |
| raise RuntimeError( | |
| "vec() must have at least one numeric argument, if it's length, dtype is not specified" | |
| ) | |
| if "dtype" in kwds: | |
| # casting constructor | |
| if len(arg_types) == 1 and types_equal( | |
| arg_types[0], vector(length=Any, dtype=Scalar), match_generic=True | |
| ): | |
| veclen = arg_types[0]._length_ | |
| vectype = kwds["dtype"] | |
| templates.append(veclen) | |
| templates.append(vectype) | |
| return vector(length=veclen, dtype=vectype) | |
| raise RuntimeError( | |
| "vec() should not have dtype specified if numeric arguments are given, the dtype will be inferred from the argument types" | |
| ) | |
| # component wise construction of an anonymous vector, e.g. wp.vec(wp.float16(1.0), wp.float16(2.0), ....) | |
| # we infer the length and data type from the number and type of the arg values | |
| veclen = len(arg_types) | |
| vectype = arg_types[0] | |
| if len(arg_types) == 1 and getattr(vectype, "_wp_generic_type_str_", None) == "vec_t": | |
| # constructor from another vector | |
| veclen = vectype._length_ | |
| vectype = vectype._wp_scalar_type_ | |
| elif not all(vectype == t for t in arg_types): | |
| raise RuntimeError( | |
| f"All numeric arguments to vec() constructor should have the same type, expected {veclen} arg_types of type {vectype}, received { ','.join(map(lambda t : str(t), arg_types)) }" | |
| ) | |
| # update the templates list, so we can generate vec<len, type>() correctly in codegen | |
| templates.append(veclen) | |
| templates.append(vectype) | |
| else: | |
| # construction of a predeclared type, e.g.: vec5d | |
| veclen, vectype = templates | |
| if len(arg_types) == 1 and getattr(arg_types[0], "_wp_generic_type_str_", None) == "vec_t": | |
| # constructor from another vector | |
| if arg_types[0]._length_ != veclen: | |
| raise RuntimeError( | |
| f"Incompatible matrix sizes for casting copy constructor, {veclen} vs {arg_types[0]._length_}" | |
| ) | |
| elif not all(vectype == t for t in arg_types): | |
| raise RuntimeError( | |
| f"All numeric arguments to vec() constructor should have the same type, expected {veclen} arg_types of type {vectype}, received { ','.join(map(lambda t : str(t), arg_types)) }" | |
| ) | |
| retvalue = vector(length=veclen, dtype=vectype) | |
| return retvalue | |
| add_builtin( | |
| "vector", | |
| input_types={"*arg_types": Scalar, "length": int, "dtype": Scalar}, | |
| variadic=True, | |
| initializer_list_func=lambda arg_types, _: len(arg_types) > 4, | |
| value_func=vector_constructor_func, | |
| native_func="vec_t", | |
| doc="Construct a vector of with given length and dtype.", | |
| group="Vector Math", | |
| export=False, | |
| ) | |
| def matrix_constructor_func(arg_types, kwds, templates): | |
| if arg_types is None: | |
| return matrix(shape=(Any, Any), dtype=Scalar) | |
| if len(templates) == 0: | |
| # anonymous construction | |
| if "shape" not in kwds: | |
| raise RuntimeError("shape keyword must be specified when calling matrix() function") | |
| if len(arg_types) == 0: | |
| if "dtype" not in kwds: | |
| raise RuntimeError("matrix() must have dtype as a keyword argument if it has no positional arguments") | |
| # zero initialization, e.g.: m = matrix(shape=(3,2), dtype=wp.float16) | |
| shape = kwds["shape"] | |
| dtype = kwds["dtype"] | |
| else: | |
| # value initialization, e.g.: m = matrix(1.0, shape=(3,2)) | |
| shape = kwds["shape"] | |
| dtype = arg_types[0] | |
| if len(arg_types) == 1 and getattr(dtype, "_wp_generic_type_str_", None) == "mat_t": | |
| # constructor from another matrix | |
| if arg_types[0]._shape_ != shape: | |
| raise RuntimeError( | |
| f"Incompatible matrix sizes for casting copy constructor, {shape} vs {arg_types[0]._shape_}" | |
| ) | |
| dtype = dtype._wp_scalar_type_ | |
| elif len(arg_types) > 1 and len(arg_types) != shape[0] * shape[1]: | |
| raise RuntimeError( | |
| "Wrong number of arguments for matrix() function, must initialize with either a scalar value, or m*n values" | |
| ) | |
| templates.append(shape[0]) | |
| templates.append(shape[1]) | |
| templates.append(dtype) | |
| else: | |
| # predeclared type, e.g.: mat32d | |
| shape = (templates[0], templates[1]) | |
| dtype = templates[2] | |
| if len(arg_types) > 0: | |
| if len(arg_types) == 1 and getattr(arg_types[0], "_wp_generic_type_str_", None) == "mat_t": | |
| # constructor from another matrix with same dimension but possibly different type | |
| if arg_types[0]._shape_ != shape: | |
| raise RuntimeError( | |
| f"Incompatible matrix sizes for casting copy constructor, {shape} vs {arg_types[0]._shape_}" | |
| ) | |
| else: | |
| # check scalar arg type matches declared type | |
| if infer_scalar_type(arg_types) != dtype: | |
| raise RuntimeError("Wrong scalar type for mat {} constructor".format(",".join(map(str, templates)))) | |
| # check vector arg type matches declared type | |
| if all(hasattr(a, "_wp_generic_type_str_") and a._wp_generic_type_str_ == "vec_t" for a in arg_types): | |
| cols = len(arg_types) | |
| if shape[1] != cols: | |
| raise RuntimeError( | |
| "Wrong number of vectors when attempting to construct a matrix with column vectors" | |
| ) | |
| if not all(a._length_ == shape[0] for a in arg_types): | |
| raise RuntimeError( | |
| "Wrong vector row count when attempting to construct a matrix with column vectors" | |
| ) | |
| else: | |
| # check that we either got 1 arg (scalar construction), or enough values for whole matrix | |
| size = shape[0] * shape[1] | |
| if len(arg_types) > 1 and len(arg_types) != size: | |
| raise RuntimeError( | |
| "Wrong number of scalars when attempting to construct a matrix from a list of components" | |
| ) | |
| return matrix(shape=shape, dtype=dtype) | |
| # only use initializer list if matrix size < 5x5, or for scalar construction | |
| def matrix_initlist_func(arg_types, templates): | |
| m, n, dtype = templates | |
| return not ( | |
| len(arg_types) == 0 | |
| or len(arg_types) == 1 # zero construction | |
| or (m == n and n < 5) # scalar construction # value construction for small matrices | |
| ) | |
| add_builtin( | |
| "matrix", | |
| input_types={"*arg_types": Scalar, "shape": Tuple[int, int], "dtype": Scalar}, | |
| variadic=True, | |
| initializer_list_func=matrix_initlist_func, | |
| value_func=matrix_constructor_func, | |
| native_func="mat_t", | |
| doc="Construct a matrix. If the positional ``arg_types`` are not given, then matrix will be zero-initialized.", | |
| group="Vector Math", | |
| export=False, | |
| ) | |
| # identity: | |
| def matrix_identity_value_func(arg_types, kwds, templates): | |
| if arg_types is None: | |
| return matrix(shape=(Any, Any), dtype=Scalar) | |
| if len(arg_types): | |
| raise RuntimeError("identity() function does not accept positional arguments") | |
| if "n" not in kwds: | |
| raise RuntimeError("'n' keyword argument must be specified when calling identity() function") | |
| if "dtype" not in kwds: | |
| raise RuntimeError("'dtype' keyword argument must be specified when calling identity() function") | |
| n, dtype = [kwds["n"], kwds["dtype"]] | |
| if n is None: | |
| raise RuntimeError("'n' must be a constant when calling identity() function") | |
| templates.append(n) | |
| templates.append(dtype) | |
| return matrix(shape=(n, n), dtype=dtype) | |
| add_builtin( | |
| "identity", | |
| input_types={"n": int, "dtype": Scalar}, | |
| value_func=matrix_identity_value_func, | |
| variadic=True, | |
| doc="Create an identity matrix with shape=(n,n) with the type given by ``dtype``.", | |
| group="Vector Math", | |
| export=False, | |
| ) | |
| def matrix_transform_value_func(arg_types, kwds, templates): | |
| if templates is None: | |
| return matrix(shape=(Any, Any), dtype=Float) | |
| if len(templates) == 0: | |
| raise RuntimeError("Cannot use a generic type name in a kernel") | |
| m, n, dtype = templates | |
| if (m, n) != (4, 4): | |
| raise RuntimeError("Can only construct 4x4 matrices with position, rotation and scale") | |
| if infer_scalar_type(arg_types) != dtype: | |
| raise RuntimeError("Wrong scalar type for mat<{}> constructor".format(",".join(map(str, templates)))) | |
| return matrix(shape=(4, 4), dtype=dtype) | |
| add_builtin( | |
| "matrix", | |
| input_types={ | |
| "pos": vector(length=3, dtype=Float), | |
| "rot": quaternion(dtype=Float), | |
| "scale": vector(length=3, dtype=Float), | |
| }, | |
| value_func=matrix_transform_value_func, | |
| native_func="mat_t", | |
| doc="""Construct a 4x4 transformation matrix that applies the transformations as | |
| Translation(pos)*Rotation(rot)*Scale(scale) when applied to column vectors, i.e.: y = (TRS)*x""", | |
| group="Vector Math", | |
| export=False, | |
| ) | |
| # not making these functions available outside kernels (export=False) as they | |
| # return data via references, which we don't currently support: | |
| add_builtin( | |
| "svd3", | |
| input_types={ | |
| "A": matrix(shape=(3, 3), dtype=Float), | |
| "U": matrix(shape=(3, 3), dtype=Float), | |
| "sigma": vector(length=3, dtype=Float), | |
| "V": matrix(shape=(3, 3), dtype=Scalar), | |
| }, | |
| value_type=None, | |
| group="Vector Math", | |
| export=False, | |
| doc="""Compute the SVD of a 3x3 matrix ``A``. The singular values are returned in ``sigma``, | |
| while the left and right basis vectors are returned in ``U`` and ``V``.""", | |
| ) | |
| add_builtin( | |
| "qr3", | |
| input_types={ | |
| "A": matrix(shape=(3, 3), dtype=Float), | |
| "Q": matrix(shape=(3, 3), dtype=Float), | |
| "R": matrix(shape=(3, 3), dtype=Float), | |
| }, | |
| value_type=None, | |
| group="Vector Math", | |
| export=False, | |
| doc="""Compute the QR decomposition of a 3x3 matrix ``A``. The orthogonal matrix is returned in ``Q``, | |
| while the upper triangular matrix is returned in ``R``.""", | |
| ) | |
| add_builtin( | |
| "eig3", | |
| input_types={ | |
| "A": matrix(shape=(3, 3), dtype=Float), | |
| "Q": matrix(shape=(3, 3), dtype=Float), | |
| "d": vector(length=3, dtype=Float), | |
| }, | |
| value_type=None, | |
| group="Vector Math", | |
| export=False, | |
| doc="""Compute the eigendecomposition of a 3x3 matrix ``A``. The eigenvectors are returned as the columns of ``Q``, | |
| while the corresponding eigenvalues are returned in ``d``.""", | |
| ) | |
| # --------------------------------- | |
| # Quaternion Math | |
| def quaternion_value_func(arg_types, kwds, templates): | |
| if arg_types is None: | |
| return quaternion(dtype=Float) | |
| if len(templates) == 0: | |
| if "dtype" in kwds: | |
| # casting constructor | |
| dtype = kwds["dtype"] | |
| else: | |
| # if constructing anonymous quat type then infer output type from arguments | |
| dtype = infer_scalar_type(arg_types) | |
| templates.append(dtype) | |
| else: | |
| # if constructing predeclared type then check arg_types match expectation | |
| if len(arg_types) > 0 and infer_scalar_type(arg_types) != templates[0]: | |
| raise RuntimeError("Wrong scalar type for quat {} constructor".format(",".join(map(str, templates)))) | |
| return quaternion(dtype=templates[0]) | |
| def quat_cast_value_func(arg_types, kwds, templates): | |
| if arg_types is None: | |
| raise RuntimeError("Missing quaternion argument.") | |
| if "dtype" not in kwds: | |
| raise RuntimeError("Missing 'dtype' kwd.") | |
| dtype = kwds["dtype"] | |
| templates.append(dtype) | |
| return quaternion(dtype=dtype) | |
| add_builtin( | |
| "quaternion", | |
| input_types={}, | |
| value_func=quaternion_value_func, | |
| native_func="quat_t", | |
| group="Quaternion Math", | |
| doc="""Construct a zero-initialized quaternion. Quaternions are laid out as | |
| [ix, iy, iz, r], where ix, iy, iz are the imaginary part, and r the real part.""", | |
| export=False, | |
| ) | |
| add_builtin( | |
| "quaternion", | |
| input_types={"x": Float, "y": Float, "z": Float, "w": Float}, | |
| value_func=quaternion_value_func, | |
| native_func="quat_t", | |
| group="Quaternion Math", | |
| doc="Create a quaternion using the supplied components (type inferred from component type).", | |
| export=False, | |
| ) | |
| add_builtin( | |
| "quaternion", | |
| input_types={"i": vector(length=3, dtype=Float), "r": Float}, | |
| value_func=quaternion_value_func, | |
| native_func="quat_t", | |
| group="Quaternion Math", | |
| doc="Create a quaternion using the supplied vector/scalar (type inferred from scalar type).", | |
| export=False, | |
| ) | |
| add_builtin( | |
| "quaternion", | |
| input_types={"q": quaternion(dtype=Float)}, | |
| value_func=quat_cast_value_func, | |
| native_func="quat_t", | |
| group="Quaternion Math", | |
| doc="Construct a quaternion of type dtype from another quaternion of a different dtype.", | |
| export=False, | |
| ) | |
| def quat_identity_value_func(arg_types, kwds, templates): | |
| # if arg_types is None then we are in 'export' mode | |
| if arg_types is None: | |
| return quatf | |
| if "dtype" not in kwds: | |
| # defaulting to float32 to preserve current behavior: | |
| dtype = float32 | |
| else: | |
| dtype = kwds["dtype"] | |
| templates.append(dtype) | |
| return quaternion(dtype=dtype) | |
| add_builtin( | |
| "quat_identity", | |
| input_types={}, | |
| value_func=quat_identity_value_func, | |
| group="Quaternion Math", | |
| doc="Construct an identity quaternion with zero imaginary part and real part of 1.0", | |
| export=True, | |
| ) | |
| add_builtin( | |
| "quat_from_axis_angle", | |
| input_types={"axis": vector(length=3, dtype=Float), "angle": Float}, | |
| value_func=lambda arg_types, kwds, _: quaternion(dtype=infer_scalar_type(arg_types)), | |
| group="Quaternion Math", | |
| doc="Construct a quaternion representing a rotation of angle radians around the given axis.", | |
| ) | |
| add_builtin( | |
| "quat_to_axis_angle", | |
| input_types={"q": quaternion(dtype=Float), "axis": vector(length=3, dtype=Float), "angle": Float}, | |
| value_type=None, | |
| group="Quaternion Math", | |
| doc="Extract the rotation axis and angle radians a quaternion represents.", | |
| ) | |
| add_builtin( | |
| "quat_from_matrix", | |
| input_types={"m": matrix(shape=(3, 3), dtype=Float)}, | |
| value_func=lambda arg_types, kwds, _: quaternion(dtype=infer_scalar_type(arg_types)), | |
| group="Quaternion Math", | |
| doc="Construct a quaternion from a 3x3 matrix.", | |
| ) | |
| add_builtin( | |
| "quat_rpy", | |
| input_types={"roll": Float, "pitch": Float, "yaw": Float}, | |
| value_func=lambda arg_types, kwds, _: quaternion(dtype=infer_scalar_type(arg_types)), | |
| group="Quaternion Math", | |
| doc="Construct a quaternion representing a combined roll (z), pitch (x), yaw rotations (y) in radians.", | |
| ) | |
| add_builtin( | |
| "quat_inverse", | |
| input_types={"q": quaternion(dtype=Float)}, | |
| value_func=lambda arg_types, kwds, _: quaternion(dtype=infer_scalar_type(arg_types)), | |
| group="Quaternion Math", | |
| doc="Compute quaternion conjugate.", | |
| ) | |
| add_builtin( | |
| "quat_rotate", | |
| input_types={"q": quaternion(dtype=Float), "p": vector(length=3, dtype=Float)}, | |
| value_func=lambda arg_types, kwds, _: vector(length=3, dtype=infer_scalar_type(arg_types)), | |
| group="Quaternion Math", | |
| doc="Rotate a vector by a quaternion.", | |
| ) | |
| add_builtin( | |
| "quat_rotate_inv", | |
| input_types={"q": quaternion(dtype=Float), "p": vector(length=3, dtype=Float)}, | |
| value_func=lambda arg_types, kwds, _: vector(length=3, dtype=infer_scalar_type(arg_types)), | |
| group="Quaternion Math", | |
| doc="Rotate a vector by the inverse of a quaternion.", | |
| ) | |
| add_builtin( | |
| "quat_slerp", | |
| input_types={"q0": quaternion(dtype=Float), "q1": quaternion(dtype=Float), "t": Float}, | |
| value_func=lambda arg_types, kwds, _: quaternion(dtype=infer_scalar_type(arg_types)), | |
| group="Quaternion Math", | |
| doc="Linearly interpolate between two quaternions.", | |
| require_original_output_arg=True, | |
| ) | |
| add_builtin( | |
| "quat_to_matrix", | |
| input_types={"q": quaternion(dtype=Float)}, | |
| value_func=lambda arg_types, kwds, _: matrix(shape=(3, 3), dtype=infer_scalar_type(arg_types)), | |
| group="Quaternion Math", | |
| doc="Convert a quaternion to a 3x3 rotation matrix.", | |
| ) | |
| add_builtin( | |
| "dot", | |
| input_types={"x": quaternion(dtype=Float), "y": quaternion(dtype=Float)}, | |
| value_func=sametype_scalar_value_func, | |
| group="Quaternion Math", | |
| doc="Compute the dot product between two quaternions.", | |
| ) | |
| # --------------------------------- | |
| # Transformations | |
| def transform_constructor_value_func(arg_types, kwds, templates): | |
| if templates is None: | |
| return transformation(dtype=Scalar) | |
| if len(templates) == 0: | |
| # if constructing anonymous transform type then infer output type from arguments | |
| dtype = infer_scalar_type(arg_types) | |
| templates.append(dtype) | |
| else: | |
| # if constructing predeclared type then check arg_types match expectation | |
| if infer_scalar_type(arg_types) != templates[0]: | |
| raise RuntimeError( | |
| f"Wrong scalar type for transform constructor expected {templates[0]}, got {','.join(map(lambda t : str(t), arg_types))}" | |
| ) | |
| return transformation(dtype=templates[0]) | |
| add_builtin( | |
| "transformation", | |
| input_types={"p": vector(length=3, dtype=Float), "q": quaternion(dtype=Float)}, | |
| value_func=transform_constructor_value_func, | |
| native_func="transform_t", | |
| group="Transformations", | |
| doc="Construct a rigid-body transformation with translation part ``p`` and rotation ``q``.", | |
| export=False, | |
| ) | |
| def transform_identity_value_func(arg_types, kwds, templates): | |
| if arg_types is None: | |
| return transformf | |
| if "dtype" not in kwds: | |
| # defaulting to float32 to preserve current behavior: | |
| dtype = float32 | |
| else: | |
| dtype = kwds["dtype"] | |
| templates.append(dtype) | |
| return transformation(dtype=dtype) | |
| add_builtin( | |
| "transform_identity", | |
| input_types={}, | |
| value_func=transform_identity_value_func, | |
| group="Transformations", | |
| doc="Construct an identity transform with zero translation and identity rotation.", | |
| export=True, | |
| ) | |
| add_builtin( | |
| "transform_get_translation", | |
| input_types={"t": transformation(dtype=Float)}, | |
| value_func=lambda arg_types, kwds, _: vector(length=3, dtype=infer_scalar_type(arg_types)), | |
| group="Transformations", | |
| doc="Return the translational part of a transform ``t``.", | |
| ) | |
| add_builtin( | |
| "transform_get_rotation", | |
| input_types={"t": transformation(dtype=Float)}, | |
| value_func=lambda arg_types, kwds, _: quaternion(dtype=infer_scalar_type(arg_types)), | |
| group="Transformations", | |
| doc="Return the rotational part of a transform ``t``.", | |
| ) | |
| add_builtin( | |
| "transform_multiply", | |
| input_types={"a": transformation(dtype=Float), "b": transformation(dtype=Float)}, | |
| value_func=lambda arg_types, kwds, _: transformation(dtype=infer_scalar_type(arg_types)), | |
| group="Transformations", | |
| doc="Multiply two rigid body transformations together.", | |
| ) | |
| add_builtin( | |
| "transform_point", | |
| input_types={"t": transformation(dtype=Scalar), "p": vector(length=3, dtype=Scalar)}, | |
| value_func=lambda arg_types, kwds, _: vector(length=3, dtype=infer_scalar_type(arg_types)), | |
| group="Transformations", | |
| doc="Apply the transform to a point ``p`` treating the homogenous coordinate as w=1 (translation and rotation).", | |
| ) | |
| add_builtin( | |
| "transform_point", | |
| input_types={"m": matrix(shape=(4, 4), dtype=Scalar), "p": vector(length=3, dtype=Scalar)}, | |
| value_func=lambda arg_types, kwds, _: vector(length=3, dtype=infer_scalar_type(arg_types)), | |
| group="Vector Math", | |
| doc="""Apply the transform to a point ``p`` treating the homogenous coordinate as w=1. | |
| The transformation is applied treating ``p`` as a column vector, e.g.: ``y = M*p``. | |
| Note this is in contrast to some libraries, notably USD, which applies transforms to row vectors, ``y^T = p^T*M^T``. | |
| If the transform is coming from a library that uses row-vectors, then users should transpose the transformation | |
| matrix before calling this method.""", | |
| ) | |
| add_builtin( | |
| "transform_vector", | |
| input_types={"t": transformation(dtype=Scalar), "v": vector(length=3, dtype=Scalar)}, | |
| value_func=lambda arg_types, kwds, _: vector(length=3, dtype=infer_scalar_type(arg_types)), | |
| group="Transformations", | |
| doc="Apply the transform to a vector ``v`` treating the homogenous coordinate as w=0 (rotation only).", | |
| ) | |
| add_builtin( | |
| "transform_vector", | |
| input_types={"m": matrix(shape=(4, 4), dtype=Scalar), "v": vector(length=3, dtype=Scalar)}, | |
| value_func=lambda arg_types, kwds, _: vector(length=3, dtype=infer_scalar_type(arg_types)), | |
| group="Vector Math", | |
| doc="""Apply the transform to a vector ``v`` treating the homogenous coordinate as w=0. | |
| The transformation is applied treating ``v`` as a column vector, e.g.: ``y = M*v`` | |
| note this is in contrast to some libraries, notably USD, which applies transforms to row vectors, ``y^T = v^T*M^T``. | |
| If the transform is coming from a library that uses row-vectors, then users should transpose the transformation | |
| matrix before calling this method.""", | |
| ) | |
| add_builtin( | |
| "transform_inverse", | |
| input_types={"t": transformation(dtype=Float)}, | |
| value_func=sametype_value_func(transformation(dtype=Float)), | |
| group="Transformations", | |
| doc="Compute the inverse of the transformation ``t``.", | |
| ) | |
| # --------------------------------- | |
| # Spatial Math | |
| def spatial_vector_constructor_value_func(arg_types, kwds, templates): | |
| if templates is None: | |
| return spatial_vector(dtype=Float) | |
| if len(templates) == 0: | |
| raise RuntimeError("Cannot use a generic type name in a kernel") | |
| vectype = templates[1] | |
| if len(arg_types) and infer_scalar_type(arg_types) != vectype: | |
| raise RuntimeError("Wrong scalar type for spatial_vector<{}> constructor".format(",".join(map(str, templates)))) | |
| return vector(length=6, dtype=vectype) | |
| add_builtin( | |
| "vector", | |
| input_types={"w": vector(length=3, dtype=Float), "v": vector(length=3, dtype=Float)}, | |
| value_func=spatial_vector_constructor_value_func, | |
| native_func="vec_t", | |
| group="Spatial Math", | |
| doc="Construct a 6D screw vector from two 3D vectors.", | |
| export=False, | |
| ) | |
| add_builtin( | |
| "spatial_adjoint", | |
| input_types={"r": matrix(shape=(3, 3), dtype=Float), "s": matrix(shape=(3, 3), dtype=Float)}, | |
| value_func=lambda arg_types, kwds, _: matrix(shape=(6, 6), dtype=infer_scalar_type(arg_types)), | |
| group="Spatial Math", | |
| doc="Construct a 6x6 spatial inertial matrix from two 3x3 diagonal blocks.", | |
| export=False, | |
| ) | |
| add_builtin( | |
| "spatial_dot", | |
| input_types={"a": vector(length=6, dtype=Float), "b": vector(length=6, dtype=Float)}, | |
| value_func=sametype_scalar_value_func, | |
| group="Spatial Math", | |
| doc="Compute the dot product of two 6D screw vectors.", | |
| ) | |
| add_builtin( | |
| "spatial_cross", | |
| input_types={"a": vector(length=6, dtype=Float), "b": vector(length=6, dtype=Float)}, | |
| value_func=sametype_value_func(vector(length=6, dtype=Float)), | |
| group="Spatial Math", | |
| doc="Compute the cross product of two 6D screw vectors.", | |
| ) | |
| add_builtin( | |
| "spatial_cross_dual", | |
| input_types={"a": vector(length=6, dtype=Float), "b": vector(length=6, dtype=Float)}, | |
| value_func=sametype_value_func(vector(length=6, dtype=Float)), | |
| group="Spatial Math", | |
| doc="Compute the dual cross product of two 6D screw vectors.", | |
| ) | |
| add_builtin( | |
| "spatial_top", | |
| input_types={"a": vector(length=6, dtype=Float)}, | |
| value_func=lambda arg_types, kwds, _: vector(length=3, dtype=arg_types[0]._wp_scalar_type_), | |
| group="Spatial Math", | |
| doc="Return the top (first) part of a 6D screw vector.", | |
| ) | |
| add_builtin( | |
| "spatial_bottom", | |
| input_types={"a": vector(length=6, dtype=Float)}, | |
| value_func=lambda arg_types, kwds, _: vector(length=3, dtype=arg_types[0]._wp_scalar_type_), | |
| group="Spatial Math", | |
| doc="Return the bottom (second) part of a 6D screw vector.", | |
| ) | |
| add_builtin( | |
| "spatial_jacobian", | |
| input_types={ | |
| "S": array(dtype=vector(length=6, dtype=Float)), | |
| "joint_parents": array(dtype=int), | |
| "joint_qd_start": array(dtype=int), | |
| "joint_start": int, | |
| "joint_count": int, | |
| "J_start": int, | |
| "J_out": array(dtype=Float), | |
| }, | |
| value_type=None, | |
| doc="", | |
| group="Spatial Math", | |
| ) | |
| add_builtin( | |
| "spatial_mass", | |
| input_types={ | |
| "I_s": array(dtype=matrix(shape=(6, 6), dtype=Float)), | |
| "joint_start": int, | |
| "joint_count": int, | |
| "M_start": int, | |
| "M": array(dtype=Float), | |
| }, | |
| value_type=None, | |
| doc="", | |
| group="Spatial Math", | |
| ) | |
| # --------------------------------- | |
| # Linear Algebra | |
| add_builtin( | |
| "dense_gemm", | |
| input_types={ | |
| "m": int, | |
| "n": int, | |
| "p": int, | |
| "t1": int, | |
| "t2": int, | |
| "A": array(dtype=float), | |
| "B": array(dtype=float), | |
| "C": array(dtype=float), | |
| }, | |
| value_type=None, | |
| doc="", | |
| group="Utility", | |
| hidden=True, | |
| ) | |
| add_builtin( | |
| "dense_gemm_batched", | |
| input_types={ | |
| "m": array(dtype=int), | |
| "n": array(dtype=int), | |
| "p": array(dtype=int), | |
| "t1": int, | |
| "t2": int, | |
| "A_start": array(dtype=int), | |
| "B_start": array(dtype=int), | |
| "C_start": array(dtype=int), | |
| "A": array(dtype=float), | |
| "B": array(dtype=float), | |
| "C": array(dtype=float), | |
| }, | |
| value_type=None, | |
| doc="", | |
| group="Utility", | |
| hidden=True, | |
| ) | |
| add_builtin( | |
| "dense_chol", | |
| input_types={"n": int, "A": array(dtype=float), "regularization": float, "L": array(dtype=float)}, | |
| value_type=None, | |
| doc="WIP", | |
| group="Utility", | |
| hidden=True, | |
| ) | |
| add_builtin( | |
| "dense_chol_batched", | |
| input_types={ | |
| "A_start": array(dtype=int), | |
| "A_dim": array(dtype=int), | |
| "A": array(dtype=float), | |
| "regularization": float, | |
| "L": array(dtype=float), | |
| }, | |
| value_type=None, | |
| doc="WIP", | |
| group="Utility", | |
| hidden=True, | |
| ) | |
| add_builtin( | |
| "dense_subs", | |
| input_types={"n": int, "L": array(dtype=float), "b": array(dtype=float), "x": array(dtype=float)}, | |
| value_type=None, | |
| doc="WIP", | |
| group="Utility", | |
| hidden=True, | |
| ) | |
| add_builtin( | |
| "dense_solve", | |
| input_types={ | |
| "n": int, | |
| "A": array(dtype=float), | |
| "L": array(dtype=float), | |
| "b": array(dtype=float), | |
| "x": array(dtype=float), | |
| }, | |
| value_type=None, | |
| doc="WIP", | |
| group="Utility", | |
| hidden=True, | |
| ) | |
| add_builtin( | |
| "dense_solve_batched", | |
| input_types={ | |
| "b_start": array(dtype=int), | |
| "A_start": array(dtype=int), | |
| "A_dim": array(dtype=int), | |
| "A": array(dtype=float), | |
| "L": array(dtype=float), | |
| "b": array(dtype=float), | |
| "x": array(dtype=float), | |
| }, | |
| value_type=None, | |
| doc="WIP", | |
| group="Utility", | |
| hidden=True, | |
| ) | |
| add_builtin( | |
| "mlp", | |
| input_types={ | |
| "weights": array(dtype=float, ndim=2), | |
| "bias": array(dtype=float, ndim=1), | |
| "activation": Callable, | |
| "index": int, | |
| "x": array(dtype=float, ndim=2), | |
| "out": array(dtype=float, ndim=2), | |
| }, | |
| value_type=None, | |
| skip_replay=True, | |
| doc="""Evaluate a multi-layer perceptron (MLP) layer in the form: ``out = act(weights*x + bias)``. | |
| :param weights: A layer's network weights with dimensions ``(m, n)``. | |
| :param bias: An array with dimensions ``(n)``. | |
| :param activation: A ``wp.func`` function that takes a single scalar float as input and returns a scalar float as output | |
| :param index: The batch item to process, typically each thread will process one item in the batch, in which case | |
| index should be ``wp.tid()`` | |
| :param x: The feature matrix with dimensions ``(n, b)`` | |
| :param out: The network output with dimensions ``(m, b)`` | |
| :note: Feature and output matrices are transposed compared to some other frameworks such as PyTorch. | |
| All matrices are assumed to be stored in flattened row-major memory layout (NumPy default).""", | |
| group="Utility", | |
| ) | |
| # --------------------------------- | |
| # Geometry | |
| add_builtin( | |
| "bvh_query_aabb", | |
| input_types={"id": uint64, "lower": vec3, "upper": vec3}, | |
| value_type=bvh_query_t, | |
| group="Geometry", | |
| doc="""Construct an axis-aligned bounding box query against a BVH object. This query can be used to iterate over all bounds | |
| inside a BVH. | |
| :param id: The BVH identifier | |
| :param lower: The lower bound of the bounding box in BVH space | |
| :param upper: The upper bound of the bounding box in BVH space""", | |
| ) | |
| add_builtin( | |
| "bvh_query_ray", | |
| input_types={"id": uint64, "start": vec3, "dir": vec3}, | |
| value_type=bvh_query_t, | |
| group="Geometry", | |
| doc="""Construct a ray query against a BVH object. This query can be used to iterate over all bounds | |
| that intersect the ray. | |
| :param id: The BVH identifier | |
| :param start: The start of the ray in BVH space | |
| :param dir: The direction of the ray in BVH space""", | |
| ) | |
| add_builtin( | |
| "bvh_query_next", | |
| input_types={"query": bvh_query_t, "index": int}, | |
| value_type=builtins.bool, | |
| group="Geometry", | |
| doc="""Move to the next bound returned by the query. | |
| The index of the current bound is stored in ``index``, returns ``False`` if there are no more overlapping bound.""", | |
| ) | |
| add_builtin( | |
| "mesh_query_point", | |
| input_types={ | |
| "id": uint64, | |
| "point": vec3, | |
| "max_dist": float, | |
| "inside": float, | |
| "face": int, | |
| "bary_u": float, | |
| "bary_v": float, | |
| }, | |
| value_type=builtins.bool, | |
| group="Geometry", | |
| doc="""Computes the closest point on the :class:`Mesh` with identifier ``id`` to the given ``point`` in space. Returns ``True`` if a point < ``max_dist`` is found. | |
| Identifies the sign of the distance using additional ray-casts to determine if the point is inside or outside. | |
| This method is relatively robust, but does increase computational cost. | |
| See below for additional sign determination methods. | |
| :param id: The mesh identifier | |
| :param point: The point in space to query | |
| :param max_dist: Mesh faces above this distance will not be considered by the query | |
| :param inside: Returns a value < 0 if query point is inside the mesh, >=0 otherwise. | |
| Note that mesh must be watertight for this to be robust | |
| :param face: Returns the index of the closest face | |
| :param bary_u: Returns the barycentric u coordinate of the closest point | |
| :param bary_v: Returns the barycentric v coordinate of the closest point""", | |
| hidden=True, | |
| ) | |
| add_builtin( | |
| "mesh_query_point", | |
| input_types={ | |
| "id": uint64, | |
| "point": vec3, | |
| "max_dist": float, | |
| }, | |
| value_type=mesh_query_point_t, | |
| group="Geometry", | |
| doc="""Computes the closest point on the :class:`Mesh` with identifier ``id`` to the given ``point`` in space. | |
| Identifies the sign of the distance using additional ray-casts to determine if the point is inside or outside. | |
| This method is relatively robust, but does increase computational cost. | |
| See below for additional sign determination methods. | |
| :param id: The mesh identifier | |
| :param point: The point in space to query | |
| :param max_dist: Mesh faces above this distance will not be considered by the query""", | |
| require_original_output_arg=True, | |
| ) | |
| add_builtin( | |
| "mesh_query_point_no_sign", | |
| input_types={ | |
| "id": uint64, | |
| "point": vec3, | |
| "max_dist": float, | |
| "face": int, | |
| "bary_u": float, | |
| "bary_v": float, | |
| }, | |
| value_type=builtins.bool, | |
| group="Geometry", | |
| doc="""Computes the closest point on the :class:`Mesh` with identifier ``id`` to the given ``point`` in space. Returns ``True`` if a point < ``max_dist`` is found. | |
| This method does not compute the sign of the point (inside/outside) which makes it faster than other point query methods. | |
| :param id: The mesh identifier | |
| :param point: The point in space to query | |
| :param max_dist: Mesh faces above this distance will not be considered by the query | |
| :param face: Returns the index of the closest face | |
| :param bary_u: Returns the barycentric u coordinate of the closest point | |
| :param bary_v: Returns the barycentric v coordinate of the closest point""", | |
| hidden=True, | |
| ) | |
| add_builtin( | |
| "mesh_query_point_no_sign", | |
| input_types={ | |
| "id": uint64, | |
| "point": vec3, | |
| "max_dist": float, | |
| }, | |
| value_type=mesh_query_point_t, | |
| group="Geometry", | |
| doc="""Computes the closest point on the :class:`Mesh` with identifier ``id`` to the given ``point`` in space. | |
| This method does not compute the sign of the point (inside/outside) which makes it faster than other point query methods. | |
| :param id: The mesh identifier | |
| :param point: The point in space to query | |
| :param max_dist: Mesh faces above this distance will not be considered by the query""", | |
| require_original_output_arg=True, | |
| ) | |
| add_builtin( | |
| "mesh_query_furthest_point_no_sign", | |
| input_types={ | |
| "id": uint64, | |
| "point": vec3, | |
| "min_dist": float, | |
| "face": int, | |
| "bary_u": float, | |
| "bary_v": float, | |
| }, | |
| value_type=builtins.bool, | |
| group="Geometry", | |
| doc="""Computes the furthest point on the mesh with identifier `id` to the given point in space. Returns ``True`` if a point > ``min_dist`` is found. | |
| This method does not compute the sign of the point (inside/outside). | |
| :param id: The mesh identifier | |
| :param point: The point in space to query | |
| :param min_dist: Mesh faces below this distance will not be considered by the query | |
| :param face: Returns the index of the furthest face | |
| :param bary_u: Returns the barycentric u coordinate of the furthest point | |
| :param bary_v: Returns the barycentric v coordinate of the furthest point""", | |
| hidden=True, | |
| ) | |
| add_builtin( | |
| "mesh_query_furthest_point_no_sign", | |
| input_types={ | |
| "id": uint64, | |
| "point": vec3, | |
| "min_dist": float, | |
| }, | |
| value_type=mesh_query_point_t, | |
| group="Geometry", | |
| doc="""Computes the furthest point on the mesh with identifier `id` to the given point in space. | |
| This method does not compute the sign of the point (inside/outside). | |
| :param id: The mesh identifier | |
| :param point: The point in space to query | |
| :param min_dist: Mesh faces below this distance will not be considered by the query""", | |
| require_original_output_arg=True, | |
| ) | |
| add_builtin( | |
| "mesh_query_point_sign_normal", | |
| input_types={ | |
| "id": uint64, | |
| "point": vec3, | |
| "max_dist": float, | |
| "inside": float, | |
| "face": int, | |
| "bary_u": float, | |
| "bary_v": float, | |
| "epsilon": float, | |
| }, | |
| defaults={"epsilon": 1.0e-3}, | |
| value_type=builtins.bool, | |
| group="Geometry", | |
| doc="""Computes the closest point on the :class:`Mesh` with identifier ``id`` to the given ``point`` in space. Returns ``True`` if a point < ``max_dist`` is found. | |
| Identifies the sign of the distance (inside/outside) using the angle-weighted pseudo normal. | |
| This approach to sign determination is robust for well conditioned meshes that are watertight and non-self intersecting. | |
| It is also comparatively fast to compute. | |
| :param id: The mesh identifier | |
| :param point: The point in space to query | |
| :param max_dist: Mesh faces above this distance will not be considered by the query | |
| :param inside: Returns a value < 0 if query point is inside the mesh, >=0 otherwise. | |
| Note that mesh must be watertight for this to be robust | |
| :param face: Returns the index of the closest face | |
| :param bary_u: Returns the barycentric u coordinate of the closest point | |
| :param bary_v: Returns the barycentric v coordinate of the closest point | |
| :param epsilon: Epsilon treating distance values as equal, when locating the minimum distance vertex/face/edge, as a | |
| fraction of the average edge length, also for treating closest point as being on edge/vertex default 1e-3""", | |
| hidden=True, | |
| ) | |
| add_builtin( | |
| "mesh_query_point_sign_normal", | |
| input_types={ | |
| "id": uint64, | |
| "point": vec3, | |
| "max_dist": float, | |
| "epsilon": float, | |
| }, | |
| defaults={"epsilon": 1.0e-3}, | |
| value_type=mesh_query_point_t, | |
| group="Geometry", | |
| doc="""Computes the closest point on the :class:`Mesh` with identifier ``id`` to the given ``point`` in space. | |
| Identifies the sign of the distance (inside/outside) using the angle-weighted pseudo normal. | |
| This approach to sign determination is robust for well conditioned meshes that are watertight and non-self intersecting. | |
| It is also comparatively fast to compute. | |
| :param id: The mesh identifier | |
| :param point: The point in space to query | |
| :param max_dist: Mesh faces above this distance will not be considered by the query | |
| :param epsilon: Epsilon treating distance values as equal, when locating the minimum distance vertex/face/edge, as a | |
| fraction of the average edge length, also for treating closest point as being on edge/vertex default 1e-3""", | |
| require_original_output_arg=True, | |
| ) | |
| add_builtin( | |
| "mesh_query_point_sign_winding_number", | |
| input_types={ | |
| "id": uint64, | |
| "point": vec3, | |
| "max_dist": float, | |
| "inside": float, | |
| "face": int, | |
| "bary_u": float, | |
| "bary_v": float, | |
| "accuracy": float, | |
| "threshold": float, | |
| }, | |
| defaults={"accuracy": 2.0, "threshold": 0.5}, | |
| value_type=builtins.bool, | |
| group="Geometry", | |
| doc="""Computes the closest point on the :class:`Mesh` with identifier ``id`` to the given point in space. Returns ``True`` if a point < ``max_dist`` is found. | |
| Identifies the sign using the winding number of the mesh relative to the query point. This method of sign determination is robust for poorly conditioned meshes | |
| and provides a smooth approximation to sign even when the mesh is not watertight. This method is the most robust and accurate of the sign determination meshes | |
| but also the most expensive. | |
| .. note:: The :class:`Mesh` object must be constructed with ``support_winding_number=True`` for this method to return correct results. | |
| :param id: The mesh identifier | |
| :param point: The point in space to query | |
| :param max_dist: Mesh faces above this distance will not be considered by the query | |
| :param inside: Returns a value < 0 if query point is inside the mesh, >=0 otherwise. | |
| Note that mesh must be watertight for this to be robust | |
| :param face: Returns the index of the closest face | |
| :param bary_u: Returns the barycentric u coordinate of the closest point | |
| :param bary_v: Returns the barycentric v coordinate of the closest point | |
| :param accuracy: Accuracy for computing the winding number with fast winding number method utilizing second-order dipole approximation, default 2.0 | |
| :param threshold: The threshold of the winding number to be considered inside, default 0.5""", | |
| hidden=True, | |
| ) | |
| add_builtin( | |
| "mesh_query_point_sign_winding_number", | |
| input_types={ | |
| "id": uint64, | |
| "point": vec3, | |
| "max_dist": float, | |
| "accuracy": float, | |
| "threshold": float, | |
| }, | |
| defaults={"accuracy": 2.0, "threshold": 0.5}, | |
| value_type=mesh_query_point_t, | |
| group="Geometry", | |
| doc="""Computes the closest point on the :class:`Mesh` with identifier ``id`` to the given point in space. | |
| Identifies the sign using the winding number of the mesh relative to the query point. This method of sign determination is robust for poorly conditioned meshes | |
| and provides a smooth approximation to sign even when the mesh is not watertight. This method is the most robust and accurate of the sign determination meshes | |
| but also the most expensive. | |
| .. note:: The :class:`Mesh` object must be constructed with ``support_winding_number=True`` for this method to return correct results. | |
| :param id: The mesh identifier | |
| :param point: The point in space to query | |
| :param max_dist: Mesh faces above this distance will not be considered by the query | |
| :param accuracy: Accuracy for computing the winding number with fast winding number method utilizing second-order dipole approximation, default 2.0 | |
| :param threshold: The threshold of the winding number to be considered inside, default 0.5""", | |
| require_original_output_arg=True, | |
| ) | |
| add_builtin( | |
| "mesh_query_ray", | |
| input_types={ | |
| "id": uint64, | |
| "start": vec3, | |
| "dir": vec3, | |
| "max_t": float, | |
| "t": float, | |
| "bary_u": float, | |
| "bary_v": float, | |
| "sign": float, | |
| "normal": vec3, | |
| "face": int, | |
| }, | |
| value_type=builtins.bool, | |
| group="Geometry", | |
| doc="""Computes the closest ray hit on the :class:`Mesh` with identifier ``id``, returns ``True`` if a hit < ``max_t`` is found. | |
| :param id: The mesh identifier | |
| :param start: The start point of the ray | |
| :param dir: The ray direction (should be normalized) | |
| :param max_t: The maximum distance along the ray to check for intersections | |
| :param t: Returns the distance of the closest hit along the ray | |
| :param bary_u: Returns the barycentric u coordinate of the closest hit | |
| :param bary_v: Returns the barycentric v coordinate of the closest hit | |
| :param sign: Returns a value > 0 if the ray hit in front of the face, returns < 0 otherwise | |
| :param normal: Returns the face normal | |
| :param face: Returns the index of the hit face""", | |
| hidden=True, | |
| ) | |
| add_builtin( | |
| "mesh_query_ray", | |
| input_types={ | |
| "id": uint64, | |
| "start": vec3, | |
| "dir": vec3, | |
| "max_t": float, | |
| }, | |
| value_type=mesh_query_ray_t, | |
| group="Geometry", | |
| doc="""Computes the closest ray hit on the :class:`Mesh` with identifier ``id``. | |
| :param id: The mesh identifier | |
| :param start: The start point of the ray | |
| :param dir: The ray direction (should be normalized) | |
| :param max_t: The maximum distance along the ray to check for intersections""", | |
| require_original_output_arg=True, | |
| ) | |
| add_builtin( | |
| "mesh_query_edge", | |
| input_types={ | |
| "id": uint64, | |
| "v1": int, | |
| "v2": int, | |
| "t": float, | |
| "bary_u": float, | |
| "bary_v": float, | |
| "sign": float, | |
| "normal": vec3, | |
| "face": int, | |
| }, | |
| value_type=bool, | |
| group="Geometry", | |
| doc="""Computes the closest edge hit on the mesh with identifier `id`, returns ``True`` if a point < ``max_t`` is found. | |
| :param id: The mesh identifier | |
| :param v1: The first vertex of the edge | |
| :param v2: The second vertex of the edge | |
| :param t: Returns the distance of the closest hit along the ray | |
| :param bary_u: Returns the barycentric u coordinate of the closest hit | |
| :param bary_v: Returns the barycentric v coordinate of the closest hit | |
| :param sign: Returns a value > 0 if the hit ray hit front of the face, returns < 0 otherwise | |
| :param normal: Returns the face normal | |
| :param face: Returns the index of the hit face""", | |
| ) | |
| add_builtin( | |
| "mesh_query_aabb", | |
| input_types={"id": uint64, "lower": vec3, "upper": vec3}, | |
| value_type=mesh_query_aabb_t, | |
| group="Geometry", | |
| doc="""Construct an axis-aligned bounding box query against a :class:`Mesh`. | |
| This query can be used to iterate over all triangles inside a volume. | |
| :param id: The mesh identifier | |
| :param lower: The lower bound of the bounding box in mesh space | |
| :param upper: The upper bound of the bounding box in mesh space""", | |
| ) | |
| add_builtin( | |
| "mesh_query_aabb_next", | |
| input_types={"query": mesh_query_aabb_t, "index": int}, | |
| value_type=builtins.bool, | |
| group="Geometry", | |
| doc="""Move to the next triangle overlapping the query bounding box. | |
| The index of the current face is stored in ``index``, returns ``False`` if there are no more overlapping triangles.""", | |
| ) | |
| add_builtin( | |
| "mesh_eval_position", | |
| input_types={"id": uint64, "face": int, "bary_u": float, "bary_v": float}, | |
| value_type=vec3, | |
| group="Geometry", | |
| doc="""Evaluates the position on the :class:`Mesh` given a face index and barycentric coordinates.""", | |
| ) | |
| add_builtin( | |
| "mesh_eval_velocity", | |
| input_types={"id": uint64, "face": int, "bary_u": float, "bary_v": float}, | |
| value_type=vec3, | |
| group="Geometry", | |
| doc="""Evaluates the velocity on the :class:`Mesh` given a face index and barycentric coordinates.""", | |
| ) | |
| add_builtin( | |
| "hash_grid_query", | |
| input_types={"id": uint64, "point": vec3, "max_dist": float}, | |
| value_type=hash_grid_query_t, | |
| group="Geometry", | |
| doc="Construct a point query against a :class:`HashGrid`. This query can be used to iterate over all neighboring points " | |
| "within a fixed radius from the query point.", | |
| ) | |
| add_builtin( | |
| "hash_grid_query_next", | |
| input_types={"query": hash_grid_query_t, "index": int}, | |
| value_type=builtins.bool, | |
| group="Geometry", | |
| doc="""Move to the next point in the hash grid query. The index of the current neighbor is stored in ``index``, returns ``False`` | |
| if there are no more neighbors.""", | |
| ) | |
| add_builtin( | |
| "hash_grid_point_id", | |
| input_types={"id": uint64, "index": int}, | |
| value_type=int, | |
| group="Geometry", | |
| doc="""Return the index of a point in the :class:`HashGrid`. This can be used to reorder threads such that grid | |
| traversal occurs in a spatially coherent order. | |
| Returns -1 if the :class:`HashGrid` has not been reserved.""", | |
| ) | |
| add_builtin( | |
| "intersect_tri_tri", | |
| input_types={"v0": vec3, "v1": vec3, "v2": vec3, "u0": vec3, "u1": vec3, "u2": vec3}, | |
| value_type=int, | |
| group="Geometry", | |
| doc="Tests for intersection between two triangles (v0, v1, v2) and (u0, u1, u2) using Moller's method. Returns > 0 if triangles intersect.", | |
| ) | |
| add_builtin( | |
| "mesh_get", | |
| input_types={"id": uint64}, | |
| value_type=Mesh, | |
| missing_grad=True, | |
| group="Geometry", | |
| doc="""Retrieves the mesh given its index.""", | |
| ) | |
| add_builtin( | |
| "mesh_eval_face_normal", | |
| input_types={"id": uint64, "face": int}, | |
| value_type=vec3, | |
| group="Geometry", | |
| doc="""Evaluates the face normal the mesh given a face index.""", | |
| ) | |
| add_builtin( | |
| "mesh_get_point", | |
| input_types={"id": uint64, "index": int}, | |
| value_type=vec3, | |
| group="Geometry", | |
| doc="""Returns the point of the mesh given a index.""", | |
| ) | |
| add_builtin( | |
| "mesh_get_velocity", | |
| input_types={"id": uint64, "index": int}, | |
| value_type=vec3, | |
| group="Geometry", | |
| doc="""Returns the velocity of the mesh given a index.""", | |
| ) | |
| add_builtin( | |
| "mesh_get_index", | |
| input_types={"id": uint64, "index": int}, | |
| value_type=int, | |
| group="Geometry", | |
| doc="""Returns the point-index of the mesh given a face-vertex index.""", | |
| ) | |
| add_builtin( | |
| "closest_point_edge_edge", | |
| input_types={"p1": vec3, "q1": vec3, "p2": vec3, "q2": vec3, "epsilon": float}, | |
| value_type=vec3, | |
| group="Geometry", | |
| doc="""Finds the closest points between two edges. Returns barycentric weights to the points on each edge, as well as the closest distance between the edges. | |
| :param p1: First point of first edge | |
| :param q1: Second point of first edge | |
| :param p2: First point of second edge | |
| :param q2: Second point of second edge | |
| :param epsilon: Zero tolerance for determining if points in an edge are degenerate. | |
| :param out: vec3 output containing (s,t,d), where `s` in [0,1] is the barycentric weight for the first edge, `t` is the barycentric weight for the second edge, and `d` is the distance between the two edges at these two closest points.""", | |
| ) | |
| # --------------------------------- | |
| # Ranges | |
| add_builtin("range", input_types={"end": int}, value_type=range_t, group="Utility", export=False, hidden=True) | |
| add_builtin( | |
| "range", input_types={"start": int, "end": int}, value_type=range_t, group="Utility", export=False, hidden=True | |
| ) | |
| add_builtin( | |
| "range", | |
| input_types={"start": int, "end": int, "step": int}, | |
| value_type=range_t, | |
| group="Utility", | |
| export=False, | |
| hidden=True, | |
| ) | |
| # --------------------------------- | |
| # Iterators | |
| add_builtin("iter_next", input_types={"range": range_t}, value_type=int, group="Utility", hidden=True) | |
| add_builtin("iter_next", input_types={"query": hash_grid_query_t}, value_type=int, group="Utility", hidden=True) | |
| add_builtin("iter_next", input_types={"query": mesh_query_aabb_t}, value_type=int, group="Utility", hidden=True) | |
| # --------------------------------- | |
| # Volumes | |
| add_builtin( | |
| "volume_sample_f", | |
| input_types={"id": uint64, "uvw": vec3, "sampling_mode": int}, | |
| value_type=float, | |
| group="Volumes", | |
| doc="""Sample the volume given by ``id`` at the volume local-space point ``uvw``. | |
| Interpolation should be :attr:`warp.Volume.CLOSEST` or :attr:`wp.Volume.LINEAR.`""", | |
| ) | |
| add_builtin( | |
| "volume_sample_grad_f", | |
| input_types={"id": uint64, "uvw": vec3, "sampling_mode": int, "grad": vec3}, | |
| value_type=float, | |
| group="Volumes", | |
| doc="""Sample the volume and its gradient given by ``id`` at the volume local-space point ``uvw``. | |
| Interpolation should be :attr:`warp.Volume.CLOSEST` or :attr:`wp.Volume.LINEAR.`""", | |
| ) | |
| add_builtin( | |
| "volume_lookup_f", | |
| input_types={"id": uint64, "i": int, "j": int, "k": int}, | |
| value_type=float, | |
| group="Volumes", | |
| doc="""Returns the value of voxel with coordinates ``i``, ``j``, ``k``. | |
| If the voxel at this index does not exist, this function returns the background value""", | |
| ) | |
| add_builtin( | |
| "volume_store_f", | |
| input_types={"id": uint64, "i": int, "j": int, "k": int, "value": float}, | |
| group="Volumes", | |
| doc="""Store ``value`` at the voxel with coordinates ``i``, ``j``, ``k``.""", | |
| ) | |
| add_builtin( | |
| "volume_sample_v", | |
| input_types={"id": uint64, "uvw": vec3, "sampling_mode": int}, | |
| value_type=vec3, | |
| group="Volumes", | |
| doc="""Sample the vector volume given by ``id`` at the volume local-space point ``uvw``. | |
| Interpolation should be :attr:`warp.Volume.CLOSEST` or :attr:`wp.Volume.LINEAR.`""", | |
| ) | |
| add_builtin( | |
| "volume_lookup_v", | |
| input_types={"id": uint64, "i": int, "j": int, "k": int}, | |
| value_type=vec3, | |
| group="Volumes", | |
| doc="""Returns the vector value of voxel with coordinates ``i``, ``j``, ``k``. | |
| If the voxel at this index does not exist, this function returns the background value.""", | |
| ) | |
| add_builtin( | |
| "volume_store_v", | |
| input_types={"id": uint64, "i": int, "j": int, "k": int, "value": vec3}, | |
| group="Volumes", | |
| doc="""Store ``value`` at the voxel with coordinates ``i``, ``j``, ``k``.""", | |
| ) | |
| add_builtin( | |
| "volume_sample_i", | |
| input_types={"id": uint64, "uvw": vec3}, | |
| value_type=int, | |
| group="Volumes", | |
| doc="""Sample the :class:`int32` volume given by ``id`` at the volume local-space point ``uvw``. """, | |
| ) | |
| add_builtin( | |
| "volume_lookup_i", | |
| input_types={"id": uint64, "i": int, "j": int, "k": int}, | |
| value_type=int, | |
| group="Volumes", | |
| doc="""Returns the :class:`int32` value of voxel with coordinates ``i``, ``j``, ``k``. | |
| If the voxel at this index does not exist, this function returns the background value.""", | |
| ) | |
| add_builtin( | |
| "volume_store_i", | |
| input_types={"id": uint64, "i": int, "j": int, "k": int, "value": int}, | |
| group="Volumes", | |
| doc="""Store ``value`` at the voxel with coordinates ``i``, ``j``, ``k``.""", | |
| ) | |
| add_builtin( | |
| "volume_index_to_world", | |
| input_types={"id": uint64, "uvw": vec3}, | |
| value_type=vec3, | |
| group="Volumes", | |
| doc="""Transform a point ``uvw`` defined in volume index space to world space given the volume's intrinsic affine transformation.""", | |
| ) | |
| add_builtin( | |
| "volume_world_to_index", | |
| input_types={"id": uint64, "xyz": vec3}, | |
| value_type=vec3, | |
| group="Volumes", | |
| doc="""Transform a point ``xyz`` defined in volume world space to the volume's index space given the volume's intrinsic affine transformation.""", | |
| ) | |
| add_builtin( | |
| "volume_index_to_world_dir", | |
| input_types={"id": uint64, "uvw": vec3}, | |
| value_type=vec3, | |
| group="Volumes", | |
| doc="""Transform a direction ``uvw`` defined in volume index space to world space given the volume's intrinsic affine transformation.""", | |
| ) | |
| add_builtin( | |
| "volume_world_to_index_dir", | |
| input_types={"id": uint64, "xyz": vec3}, | |
| value_type=vec3, | |
| group="Volumes", | |
| doc="""Transform a direction ``xyz`` defined in volume world space to the volume's index space given the volume's intrinsic affine transformation.""", | |
| ) | |
| # --------------------------------- | |
| # Random | |
| add_builtin( | |
| "rand_init", | |
| input_types={"seed": int}, | |
| value_type=uint32, | |
| group="Random", | |
| doc="Initialize a new random number generator given a user-defined seed. Returns a 32-bit integer representing the RNG state.", | |
| ) | |
| add_builtin( | |
| "rand_init", | |
| input_types={"seed": int, "offset": int}, | |
| value_type=uint32, | |
| group="Random", | |
| doc="""Initialize a new random number generator given a user-defined seed and an offset. | |
| This alternative constructor can be useful in parallel programs, where a kernel as a whole should share a seed, | |
| but each thread should generate uncorrelated values. In this case usage should be ``r = rand_init(seed, tid)``""", | |
| ) | |
| add_builtin( | |
| "randi", | |
| input_types={"state": uint32}, | |
| value_type=int, | |
| group="Random", | |
| doc="Return a random integer in the range [0, 2^32).", | |
| ) | |
| add_builtin( | |
| "randi", | |
| input_types={"state": uint32, "min": int, "max": int}, | |
| value_type=int, | |
| group="Random", | |
| doc="Return a random integer between [min, max).", | |
| ) | |
| add_builtin( | |
| "randf", | |
| input_types={"state": uint32}, | |
| value_type=float, | |
| group="Random", | |
| doc="Return a random float between [0.0, 1.0).", | |
| ) | |
| add_builtin( | |
| "randf", | |
| input_types={"state": uint32, "min": float, "max": float}, | |
| value_type=float, | |
| group="Random", | |
| doc="Return a random float between [min, max).", | |
| ) | |
| add_builtin( | |
| "randn", input_types={"state": uint32}, value_type=float, group="Random", doc="Sample a normal distribution." | |
| ) | |
| add_builtin( | |
| "sample_cdf", | |
| input_types={"state": uint32, "cdf": array(dtype=float)}, | |
| value_type=int, | |
| group="Random", | |
| doc="Inverse-transform sample a cumulative distribution function.", | |
| ) | |
| add_builtin( | |
| "sample_triangle", | |
| input_types={"state": uint32}, | |
| value_type=vec2, | |
| group="Random", | |
| doc="Uniformly sample a triangle. Returns sample barycentric coordinates.", | |
| ) | |
| add_builtin( | |
| "sample_unit_ring", | |
| input_types={"state": uint32}, | |
| value_type=vec2, | |
| group="Random", | |
| doc="Uniformly sample a ring in the xy plane.", | |
| ) | |
| add_builtin( | |
| "sample_unit_disk", | |
| input_types={"state": uint32}, | |
| value_type=vec2, | |
| group="Random", | |
| doc="Uniformly sample a disk in the xy plane.", | |
| ) | |
| add_builtin( | |
| "sample_unit_sphere_surface", | |
| input_types={"state": uint32}, | |
| value_type=vec3, | |
| group="Random", | |
| doc="Uniformly sample a unit sphere surface.", | |
| ) | |
| add_builtin( | |
| "sample_unit_sphere", | |
| input_types={"state": uint32}, | |
| value_type=vec3, | |
| group="Random", | |
| doc="Uniformly sample a unit sphere.", | |
| ) | |
| add_builtin( | |
| "sample_unit_hemisphere_surface", | |
| input_types={"state": uint32}, | |
| value_type=vec3, | |
| group="Random", | |
| doc="Uniformly sample a unit hemisphere surface.", | |
| ) | |
| add_builtin( | |
| "sample_unit_hemisphere", | |
| input_types={"state": uint32}, | |
| value_type=vec3, | |
| group="Random", | |
| doc="Uniformly sample a unit hemisphere.", | |
| ) | |
| add_builtin( | |
| "sample_unit_square", | |
| input_types={"state": uint32}, | |
| value_type=vec2, | |
| group="Random", | |
| doc="Uniformly sample a unit square.", | |
| ) | |
| add_builtin( | |
| "sample_unit_cube", | |
| input_types={"state": uint32}, | |
| value_type=vec3, | |
| group="Random", | |
| doc="Uniformly sample a unit cube.", | |
| ) | |
| add_builtin( | |
| "poisson", | |
| input_types={"state": uint32, "lam": float}, | |
| value_type=uint32, | |
| group="Random", | |
| doc="""Generate a random sample from a Poisson distribution. | |
| :param state: RNG state | |
| :param lam: The expected value of the distribution""", | |
| ) | |
| add_builtin( | |
| "noise", | |
| input_types={"state": uint32, "x": float}, | |
| value_type=float, | |
| group="Random", | |
| doc="Non-periodic Perlin-style noise in 1D.", | |
| ) | |
| add_builtin( | |
| "noise", | |
| input_types={"state": uint32, "xy": vec2}, | |
| value_type=float, | |
| group="Random", | |
| doc="Non-periodic Perlin-style noise in 2D.", | |
| ) | |
| add_builtin( | |
| "noise", | |
| input_types={"state": uint32, "xyz": vec3}, | |
| value_type=float, | |
| group="Random", | |
| doc="Non-periodic Perlin-style noise in 3D.", | |
| ) | |
| add_builtin( | |
| "noise", | |
| input_types={"state": uint32, "xyzt": vec4}, | |
| value_type=float, | |
| group="Random", | |
| doc="Non-periodic Perlin-style noise in 4D.", | |
| ) | |
| add_builtin( | |
| "pnoise", | |
| input_types={"state": uint32, "x": float, "px": int}, | |
| value_type=float, | |
| group="Random", | |
| doc="Periodic Perlin-style noise in 1D.", | |
| ) | |
| add_builtin( | |
| "pnoise", | |
| input_types={"state": uint32, "xy": vec2, "px": int, "py": int}, | |
| value_type=float, | |
| group="Random", | |
| doc="Periodic Perlin-style noise in 2D.", | |
| ) | |
| add_builtin( | |
| "pnoise", | |
| input_types={"state": uint32, "xyz": vec3, "px": int, "py": int, "pz": int}, | |
| value_type=float, | |
| group="Random", | |
| doc="Periodic Perlin-style noise in 3D.", | |
| ) | |
| add_builtin( | |
| "pnoise", | |
| input_types={"state": uint32, "xyzt": vec4, "px": int, "py": int, "pz": int, "pt": int}, | |
| value_type=float, | |
| group="Random", | |
| doc="Periodic Perlin-style noise in 4D.", | |
| ) | |
| add_builtin( | |
| "curlnoise", | |
| input_types={"state": uint32, "xy": vec2, "octaves": uint32, "lacunarity": float, "gain": float}, | |
| defaults={"octaves": 1, "lacunarity": 2.0, "gain": 0.5}, | |
| value_type=vec2, | |
| group="Random", | |
| doc="Divergence-free vector field based on the gradient of a Perlin noise function.", | |
| missing_grad=True, | |
| ) | |
| add_builtin( | |
| "curlnoise", | |
| input_types={"state": uint32, "xyz": vec3, "octaves": uint32, "lacunarity": float, "gain": float}, | |
| defaults={"octaves": 1, "lacunarity": 2.0, "gain": 0.5}, | |
| value_type=vec3, | |
| group="Random", | |
| doc="Divergence-free vector field based on the curl of three Perlin noise functions.", | |
| missing_grad=True, | |
| ) | |
| add_builtin( | |
| "curlnoise", | |
| input_types={"state": uint32, "xyzt": vec4, "octaves": uint32, "lacunarity": float, "gain": float}, | |
| defaults={"octaves": 1, "lacunarity": 2.0, "gain": 0.5}, | |
| value_type=vec3, | |
| group="Random", | |
| doc="Divergence-free vector field based on the curl of three Perlin noise functions.", | |
| missing_grad=True, | |
| ) | |
| # note printf calls directly to global CRT printf (no wp:: namespace prefix) | |
| add_builtin( | |
| "printf", | |
| input_types={}, | |
| namespace="", | |
| variadic=True, | |
| group="Utility", | |
| doc="Allows printing formatted strings using C-style format specifiers.", | |
| ) | |
| add_builtin("print", input_types={"value": Any}, doc="Print variable to stdout", export=False, group="Utility") | |
| add_builtin( | |
| "breakpoint", | |
| input_types={}, | |
| doc="Debugger breakpoint", | |
| export=False, | |
| group="Utility", | |
| namespace="", | |
| native_func="__debugbreak", | |
| ) | |
| # helpers | |
| add_builtin( | |
| "tid", | |
| input_types={}, | |
| value_type=int, | |
| export=False, | |
| group="Utility", | |
| doc="""Return the current thread index for a 1D kernel launch. Note that this is the *global* index of the thread in the range [0, dim) | |
| where dim is the parameter passed to kernel launch. This function may not be called from user-defined Warp functions.""", | |
| namespace="", | |
| native_func="builtin_tid1d", | |
| ) | |
| add_builtin( | |
| "tid", | |
| input_types={}, | |
| value_type=[int, int], | |
| group="Utility", | |
| doc="""Return the current thread indices for a 2D kernel launch. Use ``i,j = wp.tid()`` syntax to retrieve the | |
| coordinates inside the kernel thread grid. This function may not be called from user-defined Warp functions.""", | |
| namespace="", | |
| native_func="builtin_tid2d", | |
| ) | |
| add_builtin( | |
| "tid", | |
| input_types={}, | |
| value_type=[int, int, int], | |
| group="Utility", | |
| doc="""Return the current thread indices for a 3D kernel launch. Use ``i,j,k = wp.tid()`` syntax to retrieve the | |
| coordinates inside the kernel thread grid. This function may not be called from user-defined Warp functions.""", | |
| namespace="", | |
| native_func="builtin_tid3d", | |
| ) | |
| add_builtin( | |
| "tid", | |
| input_types={}, | |
| value_type=[int, int, int, int], | |
| group="Utility", | |
| doc="""Return the current thread indices for a 4D kernel launch. Use ``i,j,k,l = wp.tid()`` syntax to retrieve the | |
| coordinates inside the kernel thread grid. This function may not be called from user-defined Warp functions.""", | |
| namespace="", | |
| native_func="builtin_tid4d", | |
| ) | |
| add_builtin( | |
| "copy", | |
| input_types={"value": Any}, | |
| value_func=lambda arg_types, kwds, _: arg_types[0], | |
| hidden=True, | |
| export=False, | |
| group="Utility", | |
| ) | |
| add_builtin("assign", variadic=True, hidden=True, export=False, group="Utility") | |
| add_builtin( | |
| "select", | |
| input_types={"cond": bool, "arg1": Any, "arg2": Any}, | |
| value_func=lambda arg_types, kwds, _: arg_types[1], | |
| doc="Select between two arguments, if ``cond`` is ``False`` then return ``arg1``, otherwise return ``arg2``", | |
| group="Utility", | |
| ) | |
| add_builtin( | |
| "select", | |
| input_types={"cond": builtins.bool, "arg1": Any, "arg2": Any}, | |
| value_func=lambda args, kwds, _: args[1].type, | |
| doc="Select between two arguments, if ``cond`` is ``False`` then return ``arg1``, otherwise return ``arg2``", | |
| group="Utility", | |
| ) | |
| for t in int_types: | |
| add_builtin( | |
| "select", | |
| input_types={"cond": t, "arg1": Any, "arg2": Any}, | |
| value_func=lambda arg_types, kwds, _: arg_types[1], | |
| doc="Select between two arguments, if ``cond`` is ``False`` then return ``arg1``, otherwise return ``arg2``", | |
| group="Utility", | |
| ) | |
| add_builtin( | |
| "select", | |
| input_types={"arr": array(dtype=Any), "arg1": Any, "arg2": Any}, | |
| value_func=lambda arg_types, kwds, _: arg_types[1], | |
| doc="Select between two arguments, if ``arr`` is null then return ``arg1``, otherwise return ``arg2``", | |
| group="Utility", | |
| ) | |
| # does argument checking and type propagation for address() | |
| def address_value_func(arg_types, kwds, _): | |
| if not is_array(arg_types[0]): | |
| raise RuntimeError("load() argument 0 must be an array") | |
| num_indices = len(arg_types[1:]) | |
| num_dims = arg_types[0].ndim | |
| if num_indices < num_dims: | |
| raise RuntimeError( | |
| "Num indices < num dimensions for array load, this is a codegen error, should have generated a view instead" | |
| ) | |
| if num_indices > num_dims: | |
| raise RuntimeError( | |
| f"Num indices > num dimensions for array load, received {num_indices}, but array only has {num_dims}" | |
| ) | |
| # check index types | |
| for t in arg_types[1:]: | |
| if not type_is_int(t): | |
| raise RuntimeError(f"address() index arguments must be of integer type, got index of type {t}") | |
| return Reference(arg_types[0].dtype) | |
| # does argument checking and type propagation for view() | |
| def view_value_func(arg_types, kwds, _): | |
| if not is_array(arg_types[0]): | |
| raise RuntimeError("view() argument 0 must be an array") | |
| # check array dim big enough to support view | |
| num_indices = len(arg_types[1:]) | |
| num_dims = arg_types[0].ndim | |
| if num_indices >= num_dims: | |
| raise RuntimeError( | |
| f"Trying to create an array view with {num_indices} indices, but the array only has {num_dims} dimension(s). Ensure that the argument type on the function or kernel specifies the expected number of dimensions, e.g.: def func(param: wp.array3d(dtype=float):" | |
| ) | |
| # check index types | |
| for t in arg_types[1:]: | |
| if not type_is_int(t): | |
| raise RuntimeError(f"view() index arguments must be of integer type, got index of type {t}") | |
| # create an array view with leading dimensions removed | |
| dtype = arg_types[0].dtype | |
| ndim = num_dims - num_indices | |
| if isinstance(arg_types[0], (fabricarray, indexedfabricarray)): | |
| # fabric array of arrays: return array attribute as a regular array | |
| return array(dtype=dtype, ndim=ndim) | |
| else: | |
| return type(arg_types[0])(dtype=dtype, ndim=ndim) | |
| # does argument checking and type propagation for array_store() | |
| def array_store_value_func(arg_types, kwds, _): | |
| # check target type | |
| if not is_array(arg_types[0]): | |
| raise RuntimeError("array_store() argument 0 must be an array") | |
| num_indices = len(arg_types[1:-1]) | |
| num_dims = arg_types[0].ndim | |
| # if this happens we should have generated a view instead of a load during code gen | |
| if num_indices < num_dims: | |
| raise RuntimeError("Num indices < num dimensions for array store") | |
| if num_indices > num_dims: | |
| raise RuntimeError( | |
| f"Num indices > num dimensions for array store, received {num_indices}, but array only has {num_dims}" | |
| ) | |
| # check index types | |
| for t in arg_types[1:-1]: | |
| if not type_is_int(t): | |
| raise RuntimeError(f"array_store() index arguments must be of integer type, got index of type {t}") | |
| # check value type | |
| if not types_equal(arg_types[-1], arg_types[0].dtype): | |
| raise RuntimeError( | |
| f"array_store() value argument type ({arg_types[2]}) must be of the same type as the array ({arg_types[0].dtype})" | |
| ) | |
| return None | |
| # does argument checking for store() | |
| def store_value_func(arg_types, kwds, _): | |
| # we already stripped the Reference from the argument type prior to this call | |
| if not types_equal(arg_types[0], arg_types[1]): | |
| raise RuntimeError(f"store() value argument type ({arg_types[1]}) must be of the same type as the reference") | |
| return None | |
| # does type propagation for load() | |
| def load_value_func(arg_types, kwds, _): | |
| # we already stripped the Reference from the argument type prior to this call | |
| return arg_types[0] | |
| add_builtin("address", variadic=True, hidden=True, value_func=address_value_func, group="Utility") | |
| add_builtin("view", variadic=True, hidden=True, value_func=view_value_func, group="Utility") | |
| add_builtin( | |
| "array_store", variadic=True, hidden=True, value_func=array_store_value_func, skip_replay=True, group="Utility" | |
| ) | |
| add_builtin( | |
| "store", | |
| input_types={"address": Reference, "value": Any}, | |
| hidden=True, | |
| value_func=store_value_func, | |
| skip_replay=True, | |
| group="Utility", | |
| ) | |
| add_builtin( | |
| "load", | |
| input_types={"address": Reference}, | |
| hidden=True, | |
| value_func=load_value_func, | |
| group="Utility", | |
| ) | |
| def atomic_op_value_func(arg_types, kwds, _): | |
| # check target type | |
| if not is_array(arg_types[0]): | |
| raise RuntimeError("atomic() operation argument 0 must be an array") | |
| num_indices = len(arg_types[1:-1]) | |
| num_dims = arg_types[0].ndim | |
| # if this happens we should have generated a view instead of a load during code gen | |
| if num_indices < num_dims: | |
| raise RuntimeError("Num indices < num dimensions for atomic array operation") | |
| if num_indices > num_dims: | |
| raise RuntimeError( | |
| f"Num indices > num dimensions for atomic array operation, received {num_indices}, but array only has {num_dims}" | |
| ) | |
| # check index types | |
| for t in arg_types[1:-1]: | |
| if not type_is_int(t): | |
| raise RuntimeError(f"atomic() operation index arguments must be of integer type, got index of type {t}") | |
| if not types_equal(arg_types[-1], arg_types[0].dtype): | |
| raise RuntimeError( | |
| f"atomic() value argument ({arg_types[-1]}) must be of the same type as the array ({arg_types[0].dtype})" | |
| ) | |
| return arg_types[0].dtype | |
| for array_type in array_types: | |
| # don't list indexed array operations explicitly in docs | |
| hidden = array_type == indexedarray | |
| add_builtin( | |
| "atomic_add", | |
| hidden=hidden, | |
| input_types={"a": array_type(dtype=Any), "i": int, "value": Any}, | |
| value_func=atomic_op_value_func, | |
| doc="Atomically add ``value`` onto ``a[i]``.", | |
| group="Utility", | |
| skip_replay=True, | |
| ) | |
| add_builtin( | |
| "atomic_add", | |
| hidden=hidden, | |
| input_types={"a": array_type(dtype=Any), "i": int, "j": int, "value": Any}, | |
| value_func=atomic_op_value_func, | |
| doc="Atomically add ``value`` onto ``a[i,j]``.", | |
| group="Utility", | |
| skip_replay=True, | |
| ) | |
| add_builtin( | |
| "atomic_add", | |
| hidden=hidden, | |
| input_types={"a": array_type(dtype=Any), "i": int, "j": int, "k": int, "value": Any}, | |
| value_func=atomic_op_value_func, | |
| doc="Atomically add ``value`` onto ``a[i,j,k]``.", | |
| group="Utility", | |
| skip_replay=True, | |
| ) | |
| add_builtin( | |
| "atomic_add", | |
| hidden=hidden, | |
| input_types={"a": array_type(dtype=Any), "i": int, "j": int, "k": int, "l": int, "value": Any}, | |
| value_func=atomic_op_value_func, | |
| doc="Atomically add ``value`` onto ``a[i,j,k,l]``.", | |
| group="Utility", | |
| skip_replay=True, | |
| ) | |
| add_builtin( | |
| "atomic_sub", | |
| hidden=hidden, | |
| input_types={"a": array_type(dtype=Any), "i": int, "value": Any}, | |
| value_func=atomic_op_value_func, | |
| doc="Atomically subtract ``value`` onto ``a[i]``.", | |
| group="Utility", | |
| skip_replay=True, | |
| ) | |
| add_builtin( | |
| "atomic_sub", | |
| hidden=hidden, | |
| input_types={"a": array_type(dtype=Any), "i": int, "j": int, "value": Any}, | |
| value_func=atomic_op_value_func, | |
| doc="Atomically subtract ``value`` onto ``a[i,j]``.", | |
| group="Utility", | |
| skip_replay=True, | |
| ) | |
| add_builtin( | |
| "atomic_sub", | |
| hidden=hidden, | |
| input_types={"a": array_type(dtype=Any), "i": int, "j": int, "k": int, "value": Any}, | |
| value_func=atomic_op_value_func, | |
| doc="Atomically subtract ``value`` onto ``a[i,j,k]``.", | |
| group="Utility", | |
| skip_replay=True, | |
| ) | |
| add_builtin( | |
| "atomic_sub", | |
| hidden=hidden, | |
| input_types={"a": array_type(dtype=Any), "i": int, "j": int, "k": int, "l": int, "value": Any}, | |
| value_func=atomic_op_value_func, | |
| doc="Atomically subtract ``value`` onto ``a[i,j,k,l]``.", | |
| group="Utility", | |
| skip_replay=True, | |
| ) | |
| add_builtin( | |
| "atomic_min", | |
| hidden=hidden, | |
| input_types={"a": array_type(dtype=Any), "i": int, "value": Any}, | |
| value_func=atomic_op_value_func, | |
| doc="Compute the minimum of ``value`` and ``a[i]`` and atomically update the array.\n\n" | |
| "Note that for vectors and matrices the operation is only atomic on a per-component basis.", | |
| group="Utility", | |
| skip_replay=True, | |
| ) | |
| add_builtin( | |
| "atomic_min", | |
| hidden=hidden, | |
| input_types={"a": array_type(dtype=Any), "i": int, "j": int, "value": Any}, | |
| value_func=atomic_op_value_func, | |
| doc="Compute the minimum of ``value`` and ``a[i,j]`` and atomically update the array.\n\n" | |
| "Note that for vectors and matrices the operation is only atomic on a per-component basis.", | |
| group="Utility", | |
| skip_replay=True, | |
| ) | |
| add_builtin( | |
| "atomic_min", | |
| hidden=hidden, | |
| input_types={"a": array_type(dtype=Any), "i": int, "j": int, "k": int, "value": Any}, | |
| value_func=atomic_op_value_func, | |
| doc="Compute the minimum of ``value`` and ``a[i,j,k]`` and atomically update the array.\n\n" | |
| "Note that for vectors and matrices the operation is only atomic on a per-component basis.", | |
| group="Utility", | |
| skip_replay=True, | |
| ) | |
| add_builtin( | |
| "atomic_min", | |
| hidden=hidden, | |
| input_types={"a": array_type(dtype=Any), "i": int, "j": int, "k": int, "l": int, "value": Any}, | |
| value_func=atomic_op_value_func, | |
| doc="Compute the minimum of ``value`` and ``a[i,j,k,l]`` and atomically update the array.\n\n" | |
| "Note that for vectors and matrices the operation is only atomic on a per-component basis.", | |
| group="Utility", | |
| skip_replay=True, | |
| ) | |
| add_builtin( | |
| "atomic_max", | |
| hidden=hidden, | |
| input_types={"a": array_type(dtype=Any), "i": int, "value": Any}, | |
| value_func=atomic_op_value_func, | |
| doc="Compute the maximum of ``value`` and ``a[i]`` and atomically update the array.\n\n" | |
| "Note that for vectors and matrices the operation is only atomic on a per-component basis.", | |
| group="Utility", | |
| skip_replay=True, | |
| ) | |
| add_builtin( | |
| "atomic_max", | |
| hidden=hidden, | |
| input_types={"a": array_type(dtype=Any), "i": int, "j": int, "value": Any}, | |
| value_func=atomic_op_value_func, | |
| doc="Compute the maximum of ``value`` and ``a[i,j]`` and atomically update the array.\n\n" | |
| "Note that for vectors and matrices the operation is only atomic on a per-component basis.", | |
| group="Utility", | |
| skip_replay=True, | |
| ) | |
| add_builtin( | |
| "atomic_max", | |
| hidden=hidden, | |
| input_types={"a": array_type(dtype=Any), "i": int, "j": int, "k": int, "value": Any}, | |
| value_func=atomic_op_value_func, | |
| doc="Compute the maximum of ``value`` and ``a[i,j,k]`` and atomically update the array.\n\n" | |
| "Note that for vectors and matrices the operation is only atomic on a per-component basis.", | |
| group="Utility", | |
| skip_replay=True, | |
| ) | |
| add_builtin( | |
| "atomic_max", | |
| hidden=hidden, | |
| input_types={"a": array_type(dtype=Any), "i": int, "j": int, "k": int, "l": int, "value": Any}, | |
| value_func=atomic_op_value_func, | |
| doc="Compute the maximum of ``value`` and ``a[i,j,k,l]`` and atomically update the array.\n\n" | |
| "Note that for vectors and matrices the operation is only atomic on a per-component basis.", | |
| group="Utility", | |
| skip_replay=True, | |
| ) | |
| # used to index into builtin types, i.e.: y = vec3[1] | |
| def index_value_func(arg_types, kwds, _): | |
| return arg_types[0]._wp_scalar_type_ | |
| add_builtin( | |
| "extract", | |
| input_types={"a": vector(length=Any, dtype=Scalar), "i": int}, | |
| value_func=index_value_func, | |
| hidden=True, | |
| group="Utility", | |
| ) | |
| add_builtin( | |
| "extract", | |
| input_types={"a": quaternion(dtype=Scalar), "i": int}, | |
| value_func=index_value_func, | |
| hidden=True, | |
| group="Utility", | |
| ) | |
| add_builtin( | |
| "extract", | |
| input_types={"a": matrix(shape=(Any, Any), dtype=Scalar), "i": int}, | |
| value_func=lambda arg_types, kwds, _: vector(length=arg_types[0]._shape_[1], dtype=arg_types[0]._wp_scalar_type_), | |
| hidden=True, | |
| group="Utility", | |
| ) | |
| add_builtin( | |
| "extract", | |
| input_types={"a": matrix(shape=(Any, Any), dtype=Scalar), "i": int, "j": int}, | |
| value_func=index_value_func, | |
| hidden=True, | |
| group="Utility", | |
| ) | |
| add_builtin( | |
| "extract", | |
| input_types={"a": transformation(dtype=Scalar), "i": int}, | |
| value_func=index_value_func, | |
| hidden=True, | |
| group="Utility", | |
| ) | |
| add_builtin("extract", input_types={"s": shape_t, "i": int}, value_type=int, hidden=True, group="Utility") | |
| def vector_indexref_element_value_func(arg_types, kwds, _): | |
| vec_type = arg_types[0] | |
| # index_type = arg_types[1] | |
| value_type = vec_type._wp_scalar_type_ | |
| return Reference(value_type) | |
| # implements &vector[index] | |
| add_builtin( | |
| "index", | |
| input_types={"a": vector(length=Any, dtype=Scalar), "i": int}, | |
| value_func=vector_indexref_element_value_func, | |
| hidden=True, | |
| group="Utility", | |
| skip_replay=True, | |
| ) | |
| # implements &(*vector)[index] | |
| add_builtin( | |
| "indexref", | |
| input_types={"a": Reference, "i": int}, | |
| value_func=vector_indexref_element_value_func, | |
| hidden=True, | |
| group="Utility", | |
| skip_replay=True, | |
| ) | |
| def matrix_indexref_element_value_func(arg_types, kwds, _): | |
| mat_type = arg_types[0] | |
| # row_type = arg_types[1] | |
| # col_type = arg_types[2] | |
| value_type = mat_type._wp_scalar_type_ | |
| return Reference(value_type) | |
| def matrix_indexref_row_value_func(arg_types, kwds, _): | |
| mat_type = arg_types[0] | |
| row_type = mat_type._wp_row_type_ | |
| # value_type = arg_types[2] | |
| return Reference(row_type) | |
| # implements matrix[i] = row | |
| add_builtin( | |
| "index", | |
| input_types={"a": matrix(shape=(Any, Any), dtype=Scalar), "i": int}, | |
| value_func=matrix_indexref_row_value_func, | |
| hidden=True, | |
| group="Utility", | |
| skip_replay=True, | |
| ) | |
| # implements matrix[i,j] = scalar | |
| add_builtin( | |
| "index", | |
| input_types={"a": matrix(shape=(Any, Any), dtype=Scalar), "i": int, "j": int}, | |
| value_func=matrix_indexref_element_value_func, | |
| hidden=True, | |
| group="Utility", | |
| skip_replay=True, | |
| ) | |
| for t in scalar_types + vector_types + [builtins.bool]: | |
| if "vec" in t.__name__ or "mat" in t.__name__: | |
| continue | |
| add_builtin( | |
| "expect_eq", | |
| input_types={"arg1": t, "arg2": t}, | |
| value_type=None, | |
| doc="Prints an error to stdout if ``arg1`` and ``arg2`` are not equal", | |
| group="Utility", | |
| hidden=True, | |
| ) | |
| def expect_eq_val_func(arg_types, kwds, _): | |
| if not types_equal(arg_types[0], arg_types[1]): | |
| raise RuntimeError("Can't test equality for objects with different types") | |
| return None | |
| add_builtin( | |
| "expect_eq", | |
| input_types={"arg1": vector(length=Any, dtype=Scalar), "arg2": vector(length=Any, dtype=Scalar)}, | |
| value_func=expect_eq_val_func, | |
| doc="Prints an error to stdout if ``arg1`` and ``arg2`` are not equal", | |
| group="Utility", | |
| hidden=True, | |
| ) | |
| add_builtin( | |
| "expect_neq", | |
| input_types={"arg1": vector(length=Any, dtype=Scalar), "arg2": vector(length=Any, dtype=Scalar)}, | |
| value_func=expect_eq_val_func, | |
| doc="Prints an error to stdout if ``arg1`` and ``arg2`` are equal", | |
| group="Utility", | |
| hidden=True, | |
| ) | |
| add_builtin( | |
| "expect_eq", | |
| input_types={"arg1": matrix(shape=(Any, Any), dtype=Scalar), "arg2": matrix(shape=(Any, Any), dtype=Scalar)}, | |
| value_func=expect_eq_val_func, | |
| doc="Prints an error to stdout if ``arg1`` and ``arg2`` are not equal", | |
| group="Utility", | |
| hidden=True, | |
| ) | |
| add_builtin( | |
| "expect_neq", | |
| input_types={"arg1": matrix(shape=(Any, Any), dtype=Scalar), "arg2": matrix(shape=(Any, Any), dtype=Scalar)}, | |
| value_func=expect_eq_val_func, | |
| doc="Prints an error to stdout if ``arg1`` and ``arg2`` are equal", | |
| group="Utility", | |
| hidden=True, | |
| ) | |
| add_builtin( | |
| "lerp", | |
| input_types={"a": Float, "b": Float, "t": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="Linearly interpolate two values ``a`` and ``b`` using factor ``t``, computed as ``a*(1-t) + b*t``", | |
| group="Utility", | |
| ) | |
| add_builtin( | |
| "smoothstep", | |
| input_types={"edge0": Float, "edge1": Float, "x": Float}, | |
| value_func=sametype_value_func(Float), | |
| doc="""Smoothly interpolate between two values ``edge0`` and ``edge1`` using a factor ``x``, | |
| and return a result between 0 and 1 using a cubic Hermite interpolation after clamping.""", | |
| group="Utility", | |
| ) | |
| def lerp_value_func(default): | |
| def fn(arg_types, kwds, _): | |
| if arg_types is None: | |
| return default | |
| scalar_type = arg_types[-1] | |
| if not types_equal(arg_types[0], arg_types[1]): | |
| raise RuntimeError("Can't lerp between objects with different types") | |
| if arg_types[0]._wp_scalar_type_ != scalar_type: | |
| raise RuntimeError("'t' parameter must have the same scalar type as objects you're lerping between") | |
| return arg_types[0] | |
| return fn | |
| add_builtin( | |
| "lerp", | |
| input_types={"a": vector(length=Any, dtype=Float), "b": vector(length=Any, dtype=Float), "t": Float}, | |
| value_func=lerp_value_func(vector(length=Any, dtype=Float)), | |
| doc="Linearly interpolate two values ``a`` and ``b`` using factor ``t``, computed as ``a*(1-t) + b*t``", | |
| group="Utility", | |
| ) | |
| add_builtin( | |
| "lerp", | |
| input_types={"a": matrix(shape=(Any, Any), dtype=Float), "b": matrix(shape=(Any, Any), dtype=Float), "t": Float}, | |
| value_func=lerp_value_func(matrix(shape=(Any, Any), dtype=Float)), | |
| doc="Linearly interpolate two values ``a`` and ``b`` using factor ``t``, computed as ``a*(1-t) + b*t``", | |
| group="Utility", | |
| ) | |
| add_builtin( | |
| "lerp", | |
| input_types={"a": quaternion(dtype=Float), "b": quaternion(dtype=Float), "t": Float}, | |
| value_func=lerp_value_func(quaternion(dtype=Float)), | |
| doc="Linearly interpolate two values ``a`` and ``b`` using factor ``t``, computed as ``a*(1-t) + b*t``", | |
| group="Utility", | |
| ) | |
| add_builtin( | |
| "lerp", | |
| input_types={"a": transformation(dtype=Float), "b": transformation(dtype=Float), "t": Float}, | |
| value_func=lerp_value_func(transformation(dtype=Float)), | |
| doc="Linearly interpolate two values ``a`` and ``b`` using factor ``t``, computed as ``a*(1-t) + b*t``", | |
| group="Utility", | |
| ) | |
| # fuzzy compare for float values | |
| add_builtin( | |
| "expect_near", | |
| input_types={"arg1": Float, "arg2": Float, "tolerance": Float}, | |
| defaults={"tolerance": 1.0e-6}, | |
| value_type=None, | |
| doc="Prints an error to stdout if ``arg1`` and ``arg2`` are not closer than tolerance in magnitude", | |
| group="Utility", | |
| ) | |
| add_builtin( | |
| "expect_near", | |
| input_types={"arg1": vec3, "arg2": vec3, "tolerance": float}, | |
| value_type=None, | |
| doc="Prints an error to stdout if any element of ``arg1`` and ``arg2`` are not closer than tolerance in magnitude", | |
| group="Utility", | |
| ) | |
| # --------------------------------- | |
| # Algorithms | |
| add_builtin( | |
| "lower_bound", | |
| input_types={"arr": array(dtype=Scalar), "value": Scalar}, | |
| value_type=int, | |
| doc="Search a sorted array ``arr`` for the closest element greater than or equal to ``value``.", | |
| ) | |
| add_builtin( | |
| "lower_bound", | |
| input_types={"arr": array(dtype=Scalar), "arr_begin": int, "arr_end": int, "value": Scalar}, | |
| value_type=int, | |
| doc="Search a sorted array ``arr`` in the range [arr_begin, arr_end) for the closest element greater than or equal to ``value``.", | |
| ) | |
| # --------------------------------- | |
| # Operators | |
| add_builtin( | |
| "add", input_types={"x": Scalar, "y": Scalar}, value_func=sametype_value_func(Scalar), doc="", group="Operators" | |
| ) | |
| add_builtin( | |
| "add", | |
| input_types={"x": vector(length=Any, dtype=Scalar), "y": vector(length=Any, dtype=Scalar)}, | |
| value_func=sametype_value_func(vector(length=Any, dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "add", | |
| input_types={"x": quaternion(dtype=Scalar), "y": quaternion(dtype=Scalar)}, | |
| value_func=sametype_value_func(quaternion(dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "add", | |
| input_types={"x": matrix(shape=(Any, Any), dtype=Scalar), "y": matrix(shape=(Any, Any), dtype=Scalar)}, | |
| value_func=sametype_value_func(matrix(shape=(Any, Any), dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "add", | |
| input_types={"x": transformation(dtype=Scalar), "y": transformation(dtype=Scalar)}, | |
| value_func=sametype_value_func(transformation(dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "sub", input_types={"x": Scalar, "y": Scalar}, value_func=sametype_value_func(Scalar), doc="", group="Operators" | |
| ) | |
| add_builtin( | |
| "sub", | |
| input_types={"x": vector(length=Any, dtype=Scalar), "y": vector(length=Any, dtype=Scalar)}, | |
| value_func=sametype_value_func(vector(length=Any, dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "sub", | |
| input_types={"x": matrix(shape=(Any, Any), dtype=Scalar), "y": matrix(shape=(Any, Any), dtype=Scalar)}, | |
| value_func=sametype_value_func(matrix(shape=(Any, Any), dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "sub", | |
| input_types={"x": quaternion(dtype=Scalar), "y": quaternion(dtype=Scalar)}, | |
| value_func=sametype_value_func(quaternion(dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "sub", | |
| input_types={"x": transformation(dtype=Scalar), "y": transformation(dtype=Scalar)}, | |
| value_func=sametype_value_func(transformation(dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| # bitwise operators | |
| add_builtin("bit_and", input_types={"x": Int, "y": Int}, value_func=sametype_value_func(Int), doc="", group="Operators") | |
| add_builtin("bit_or", input_types={"x": Int, "y": Int}, value_func=sametype_value_func(Int), doc="", group="Operators") | |
| add_builtin("bit_xor", input_types={"x": Int, "y": Int}, value_func=sametype_value_func(Int), doc="", group="Operators") | |
| add_builtin("lshift", input_types={"x": Int, "y": Int}, value_func=sametype_value_func(Int), doc="", group="Operators") | |
| add_builtin("rshift", input_types={"x": Int, "y": Int}, value_func=sametype_value_func(Int), doc="", group="Operators") | |
| add_builtin("invert", input_types={"x": Int}, value_func=sametype_value_func(Int), doc="", group="Operators") | |
| def scalar_mul_value_func(default): | |
| def fn(arg_types, kwds, _): | |
| if arg_types is None: | |
| return default | |
| scalar = [t for t in arg_types if t in scalar_types][0] | |
| compound = [t for t in arg_types if t not in scalar_types][0] | |
| if scalar != compound._wp_scalar_type_: | |
| raise RuntimeError("Object and coefficient must have the same scalar type when multiplying by scalar") | |
| return compound | |
| return fn | |
| def mul_matvec_value_func(arg_types, kwds, _): | |
| if arg_types is None: | |
| return vector(length=Any, dtype=Scalar) | |
| if arg_types[0]._wp_scalar_type_ != arg_types[1]._wp_scalar_type_: | |
| raise RuntimeError( | |
| f"Can't multiply matrix and vector with different types {arg_types[0]._wp_scalar_type_}, {arg_types[1]._wp_scalar_type_}" | |
| ) | |
| if arg_types[0]._shape_[1] != arg_types[1]._length_: | |
| raise RuntimeError( | |
| f"Can't multiply matrix of shape {arg_types[0]._shape_} and vector with length {arg_types[1]._length_}" | |
| ) | |
| return vector(length=arg_types[0]._shape_[0], dtype=arg_types[0]._wp_scalar_type_) | |
| def mul_vecmat_value_func(arg_types, kwds, _): | |
| if arg_types is None: | |
| return vector(length=Any, dtype=Scalar) | |
| if arg_types[1]._wp_scalar_type_ != arg_types[0]._wp_scalar_type_: | |
| raise RuntimeError( | |
| f"Can't multiply vector and matrix with different types {arg_types[1]._wp_scalar_type_}, {arg_types[0]._wp_scalar_type_}" | |
| ) | |
| if arg_types[1]._shape_[0] != arg_types[0]._length_: | |
| raise RuntimeError( | |
| f"Can't multiply vector with length {arg_types[0]._length_} and matrix of shape {arg_types[1]._shape_}" | |
| ) | |
| return vector(length=arg_types[1]._shape_[1], dtype=arg_types[1]._wp_scalar_type_) | |
| def mul_matmat_value_func(arg_types, kwds, _): | |
| if arg_types is None: | |
| return matrix(length=Any, dtype=Scalar) | |
| if arg_types[0]._wp_scalar_type_ != arg_types[1]._wp_scalar_type_: | |
| raise RuntimeError( | |
| f"Can't multiply matrices with different types {arg_types[0]._wp_scalar_type_}, {arg_types[1]._wp_scalar_type_}" | |
| ) | |
| if arg_types[0]._shape_[1] != arg_types[1]._shape_[0]: | |
| raise RuntimeError(f"Can't multiply matrix of shapes {arg_types[0]._shape_} and {arg_types[1]._shape_}") | |
| return matrix(shape=(arg_types[0]._shape_[0], arg_types[1]._shape_[1]), dtype=arg_types[0]._wp_scalar_type_) | |
| add_builtin( | |
| "mul", input_types={"x": Scalar, "y": Scalar}, value_func=sametype_value_func(Scalar), doc="", group="Operators" | |
| ) | |
| add_builtin( | |
| "mul", | |
| input_types={"x": vector(length=Any, dtype=Scalar), "y": Scalar}, | |
| value_func=scalar_mul_value_func(vector(length=Any, dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "mul", | |
| input_types={"x": Scalar, "y": vector(length=Any, dtype=Scalar)}, | |
| value_func=scalar_mul_value_func(vector(length=Any, dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "mul", | |
| input_types={"x": quaternion(dtype=Scalar), "y": Scalar}, | |
| value_func=scalar_mul_value_func(quaternion(dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "mul", | |
| input_types={"x": Scalar, "y": quaternion(dtype=Scalar)}, | |
| value_func=scalar_mul_value_func(quaternion(dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "mul", | |
| input_types={"x": quaternion(dtype=Scalar), "y": quaternion(dtype=Scalar)}, | |
| value_func=sametype_value_func(quaternion(dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "mul", | |
| input_types={"x": Scalar, "y": matrix(shape=(Any, Any), dtype=Scalar)}, | |
| value_func=scalar_mul_value_func(matrix(shape=(Any, Any), dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "mul", | |
| input_types={"x": matrix(shape=(Any, Any), dtype=Scalar), "y": Scalar}, | |
| value_func=scalar_mul_value_func(matrix(shape=(Any, Any), dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "mul", | |
| input_types={"x": matrix(shape=(Any, Any), dtype=Scalar), "y": vector(length=Any, dtype=Scalar)}, | |
| value_func=mul_matvec_value_func, | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "mul", | |
| input_types={"x": vector(length=Any, dtype=Scalar), "y": matrix(shape=(Any, Any), dtype=Scalar)}, | |
| value_func=mul_vecmat_value_func, | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "mul", | |
| input_types={"x": matrix(shape=(Any, Any), dtype=Scalar), "y": matrix(shape=(Any, Any), dtype=Scalar)}, | |
| value_func=mul_matmat_value_func, | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "mul", | |
| input_types={"x": transformation(dtype=Scalar), "y": transformation(dtype=Scalar)}, | |
| value_func=sametype_value_func(transformation(dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "mul", | |
| input_types={"x": Scalar, "y": transformation(dtype=Scalar)}, | |
| value_func=scalar_mul_value_func(transformation(dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "mul", | |
| input_types={"x": transformation(dtype=Scalar), "y": Scalar}, | |
| value_func=scalar_mul_value_func(transformation(dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "mod", input_types={"x": Scalar, "y": Scalar}, value_func=sametype_value_func(Scalar), doc="", group="Operators" | |
| ) | |
| add_builtin( | |
| "div", | |
| input_types={"x": Scalar, "y": Scalar}, | |
| value_func=sametype_value_func(Scalar), | |
| doc="", group="Operators", | |
| require_original_output_arg=True, | |
| ) | |
| add_builtin( | |
| "div", | |
| input_types={"x": vector(length=Any, dtype=Scalar), "y": Scalar}, | |
| value_func=scalar_mul_value_func(vector(length=Any, dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "div", | |
| input_types={"x": Scalar, "y": vector(length=Any, dtype=Scalar)}, | |
| value_func=scalar_mul_value_func(vector(length=Any, dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "div", | |
| input_types={"x": matrix(shape=(Any, Any), dtype=Scalar), "y": Scalar}, | |
| value_func=scalar_mul_value_func(matrix(shape=(Any, Any), dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "div", | |
| input_types={"x": Scalar, "y": matrix(shape=(Any, Any), dtype=Scalar)}, | |
| value_func=scalar_mul_value_func(matrix(shape=(Any, Any), dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "div", | |
| input_types={"x": quaternion(dtype=Scalar), "y": Scalar}, | |
| value_func=scalar_mul_value_func(quaternion(dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "div", | |
| input_types={"x": Scalar, "y": quaternion(dtype=Scalar)}, | |
| value_func=scalar_mul_value_func(quaternion(dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "floordiv", | |
| input_types={"x": Scalar, "y": Scalar}, | |
| value_func=sametype_value_func(Scalar), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin("pos", input_types={"x": Scalar}, value_func=sametype_value_func(Scalar), doc="", group="Operators") | |
| add_builtin( | |
| "pos", | |
| input_types={"x": vector(length=Any, dtype=Scalar)}, | |
| value_func=sametype_value_func(vector(length=Any, dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "pos", | |
| input_types={"x": quaternion(dtype=Scalar)}, | |
| value_func=sametype_value_func(quaternion(dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "pos", | |
| input_types={"x": matrix(shape=(Any, Any), dtype=Scalar)}, | |
| value_func=sametype_value_func(matrix(shape=(Any, Any), dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin("neg", input_types={"x": Scalar}, value_func=sametype_value_func(Scalar), doc="", group="Operators") | |
| add_builtin( | |
| "neg", | |
| input_types={"x": vector(length=Any, dtype=Scalar)}, | |
| value_func=sametype_value_func(vector(length=Any, dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "neg", | |
| input_types={"x": quaternion(dtype=Scalar)}, | |
| value_func=sametype_value_func(quaternion(dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin( | |
| "neg", | |
| input_types={"x": matrix(shape=(Any, Any), dtype=Scalar)}, | |
| value_func=sametype_value_func(matrix(shape=(Any, Any), dtype=Scalar)), | |
| doc="", | |
| group="Operators", | |
| ) | |
| add_builtin("unot", input_types={"b": builtins.bool}, value_type=builtins.bool, doc="", group="Operators") | |
| for t in int_types: | |
| add_builtin("unot", input_types={"b": t}, value_type=builtins.bool, doc="", group="Operators") | |
| add_builtin("unot", input_types={"a": array(dtype=Any)}, value_type=builtins.bool, doc="", group="Operators") | |